2.3. Cabeceras y códigos

Veremos a continuación cómo tratar las cabeceras HTTP de una petición y de una respuesta, así como los códigos de estado que emite un servidor Web ante una petición, y las variables CGI a las que podemos acceder. 

2.3.1. Cabeceras de petición

Cuando se envía una petición HTTP, se pueden enviar, entre otras cosas, unas cabeceras con información sobre el navegador. Para leer estas cabeceras de una petición desde un servlet, se utiliza el método getHeader() del objeto HttpServletRequest

String getHeader(String nombre)

El parámetro indica el nombre de la cabecera cuyo valor se quiere obtener. Devuelve el valor de la cabecera, o null si la cabecera no ha sido enviada en la petición.

Se tienen otros métodos, como:

String[] getHeaderNames()
String[] getHeaders(String nombre)
int getIntHeader(String nombre)
...

Con getHeaderNames() obtendremos todos los nombres de las cabeceras enviadas. Con getHeaders() obtendremos todos los valores de la cabecera de nombre dado. También hay métodos como getIntHeader() que devuelve el valor de una cabecera con un tipo de dato específico (entero, en este caso). Los nombres de las cabeceras normalmente no distinguen mayúsculas de minúsculas.

Algunas cabeceras son de uso común, y tienen métodos específicos para obtener sus valores, como:

Cookie[] getCookies()
String getContentLength()
String getContentType()
...

Con getCookies() obtendremos todas las cookies de la petición (veremos las cookies con más detalle más adelante). Con getContentLength() obtenemos el valor de la cabecera Content-Length, y con getContentType() el de la cabecera Content-Type.

2.3.2. Cabeceras de respuesta

En la respuesta de un servidor web a una petición también pueden aparecer cabeceras que informan sobre el documento servido o sobre el propio servidor. Podemos definir cabeceras de respuesta para enviar cookies, indicar la fecha de modificación, etc. Estas cabeceras deben establecerse ANTES de enviar cualquier documento, o antes de obtener el PrintWriter si es el caso.

Para enviar cabeceras, el método más general es setHeader() del objeto HttpServletResponse

void setHeader(String nombre, String valor)

Al que se le pasan el nombre de la cabecera y el valor. Hay otros métodos útiles:

void setIntHeader(String nombre, int valor)
void addHeader(String nombre, String valor)
void addIntHeader(String nombre, int valor)
...

setIntHeader() o setDateHeader() se utilizan para enviar cabeceras de tipo entero o fecha. Los métodos add...() se emplean para añadir múltiples valores a una cabecera con el mismo nombre.

Algunas cabeceras tienen métodos específicos de envío, como:

void setContentType(String tipo)
void setContentLength(int tamaño)
void sendRedirect(String url)
void addCookie(Cookie cookie)

Con setContentType() se establece la cabecera Content-Type con el tipo MIME del documento. Con setContentLength() se indican los bytes enviados. Con sendRedirect() se selecciona la cabecera Location. Finalmente, con addCookie() se establecen cookies (esto último ya lo veremos con más detalle más adelante). Es recomendable utilizar estos métodos en lugar del método setHeader() para la cabecera en cuestión.

2.3.3. Variables CGI

Las variables CGI son una forma de recoger información sobre una petición. Algunas se derivan de la línea de petición HTTP y de las cabeceras, otras del propio socket (como el nombre o la IP de quien solicita la petición), y otras de los parámetros de instalación del servidor (como el mapeo de URLs a los paths actuales).

Mostramos a continuación una tabla con las variables CGI, y cómo acceder a ellas desde servlets:

VARIABLE CGI SIGNIFICADO

ACCESO DESDE SERVLETS

AUTH_TYPE Tipo de cabecera Authorization (basic o digest) request.getAuthType()
CONTENT_LENGTH Número de bytes enviados en peticiones POST request.getContentLength()
CONTENT_TYPE Tipo MIME de los datos adjuntos request.getContentType()
DOCUMENT_ROOT Path del directorio raíz del servidor web getServletContext().getRealPath("/")
HTTP_XXX_YYY Acceso a cabeceras arbitrarias HTTP request.getHeader("Xxx-Yyy")
PATH_INFO Información de path adjunto a la URL request.getPathInfo()
PATH_TRANSLATED Path mapeado al path real del servidor request.getPathTranslated()
QUERY_STRING Datos adjuntos para peticiones GET request.getQueryString()
REMOTE_ADDR IP del cliente que hizo la petición request.getRemoteAddr()
REMOTE_HOST Nombre del dominio del cliente que hizo la petición (o IP si no se puede determinar) request.getRemoteHost()
REMOTE_USER Parte del usuario en la cabecera Authorization (si se suministró) request.getRemoteUser()
REQUEST_METHOD Tipo de petición (GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE) request.getMethod()
SCRIPT_NAME Path del servlet request.getServletPath()
SERVER_NAME Nombre del servidor web request.getServerName()
SERVER_PORT Puerto por el que escucha el servidor request.getServerPort()
SERVER_PROTOCOL Nombre y versión usada en la línea de petición (HTTP/1.0, HTTP/1.1 ...) request.getServerProtocol()
SERVER_SOFTWARE Información del servidor web getServletContext().getServerInfo()

request se asume que es un objeto de tipo HttpServletRequest. Para obtener cualquiera de las variables antes mencionadas, sólo hay que llamar al método apropiado desde doGet() o doPost().

2.3.4. Códigos de estado HTTP

Cuando un servidor web responde a una petición, en la respuesta aparece, entre otras cosas, un código de estado que indica el resultado de la petición, y un mensaje corto descriptivo de dicho código.

El envío de cabeceras de respuesta normalmente se planifica junto con el envío de códigos de estado, ya que muchos de los códigos de estado necesitan tener una cabecera definida. Podemos hacer varias cosas con los servlets manipulando las líneas de estado y las cabeceras de respuesta, como por ejemplo reenviar al usuario a otros lugares, indicar que se requiere un password para acceder a un determinado sitio web, etc.

Para enviar códigos de estado se emplea el método setStatus() de HttpServletResponse:

void setStatus(int estado)

Donde se le pasa como parámetro el código del estado. En la clase HttpServletResponse tenemos una serie de constantes para referenciar a cada código de estado. Por ejemplo, la constante:

HttpServletResponse.SC_NOT_FOUND

se corresponde con el código 404, e indica que el documento solicitado no se ha encontrado.

Existen otros métodos para gestión de mensajes de error:

void sendError(int codigo, String mensaje)
void sendRedirect(String url)

sendError() genera una página de error, con código de error igual a codigo, y con mensaje de error igual a mensaje. Se suele utilizar este método para códigos de error, y setStatus() para códigos normales.

sendRedirect() genera un código de tipo 302 (redirección), envía una cabecera Location y redirige a la página indicada en url. Es mejor que enviar directamente el código, o hacer un response.setHeader("Location", "http..."), porque es más cómodo, y porque el servlet genera así una página con el enlace a la nueva dirección, para navegadores que no soporten redirección automática

Si queremos enviar un código en la respuesta, se tiene que especificar antes de obtener el objeto PrintWriter.

2.3.5. Ejemplos

1. Ejemplo de cabeceras de petición

El siguiente servlet muestra los valores de todas las cabeceras HTTP enviadas en la petición. Recorre las cabeceras enviadas y muestra su nombre y valor:

import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletCabecerasPeticion 
extends HttpServlet
{
   // Metodo para GET

   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response) 
   throws ServletException, IOException
   {
	PrintWriter out = response.getWriter();

	// Mostramos las cabeceras enviadas 
	// en la peticion

	out.println ("<HTML>");
	out.println ("<BODY>");	
	out.println ("<H1>Cabeceras</H1>");
	out.println ("<BR>");

	Enumeration cabeceras = request.getHeaderNames();

	while (cabeceras.hasMoreElements())
	{		
		String nombre = (String)(cabeceras.nextElement());
		out.println ("Nombre: " + nombre + 
		   ", Valor: " + request.getHeader(nombre));
		out.println ("<BR><BR>");
	}

	out.println ("</BODY>");			
	out.println ("</HTML>");
   }	

   // Metodo para POST
	
   public void doPost(HttpServletRequest request, 
                      HttpServletResponse response) 
   throws ServletException, IOException
   {
	doGet(request, response);
   }	
}

Se puede probar con este formulario, pinchando el botón:

<html>
<body>
<form action=
 "/ejemplocabeceras/servlet/ServletCabecerasPeticion">
	<input type="submit" value="Pulsa aqui">
</form>
</body>
</html>

2. Ejemplo de cabeceras de respuesta

El siguiente servlet espera un parámetro accion que puede tomar 4 valores:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletCabecerasRespuesta 
extends HttpServlet implements Runnable
{
   // Ultimo numero primo descubierto
   long primo = 1;			
   // Hilo para calcular numeros primos
   Thread t = new Thread(this);	
	
   // Metodo de inicializacion
	
   public void init()
   {
	t.start();
   }
	
   // Metodo para GET
	
   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response) 
   throws ServletException, IOException
   {	
	String accion = request.getParameter("accion");
	
	if (accion.equals("primo"))
	{
		// Buscar el ultimo numero 
		// primo y enviarlo

		response.setContentType("text/html");
		response.setHeader("Refresh", "10");
		PrintWriter out = response.getWriter();
		out.println ("<HTML><BODY>");
		out.println ("Primo: " + primo);
		out.println ("</BODY></HTML>");	

	} else if (accion.equals("redirect")) {

		// Redirigir a otra pagina

		String url = request.getParameter("url");
		if (url == null)
			url = "http://www.ua.es";
		response.sendRedirect(url);
			
	} else if (accion.equals("error")) {	
				
		// Enviar error con sendError()

		int codigo = response.SC_NOT_FOUND;
		try
		{
		   codigo = Integer.parseInt
		      (request.getParameter("codigoMensaje"));
		} catch (Exception ex) {
		   codigo = response.SC_NOT_FOUND;
		}
		String mensaje = request.getParameter("mensaje");
		if (mensaje == null)
		   mensaje = "Error generado";
		response.sendError(codigo, mensaje);

	} else if (accion.equals("codigo")) {

		// Enviar un codigo de error

		int codigo = response.SC_NOT_FOUND;
		try
		{
		   codigo = Integer.parseInt
		      (request.getParameter("codigo"));
		} catch (Exception ex) {
		   codigo = response.SC_NOT_FOUND;
		}
		response.setStatus(codigo);
	}
   }	

   // Metodo para POST
	
   public void doPost(HttpServletRequest request, 
                      HttpServletResponse response) 
   throws ServletException, IOException
   {
	doGet(request, response);
   }

   ... el resto del codigo es para el hilo, 
   para calcular numeros primos
   Puede consultarse en el fichero fuente, 
   aqui se quita por simplificar
}

Se puede probar con este formulario, eligiendo la acción a realizar, introduciendo los parámetros necesarios en el formulario y pinchando el botón de Enviar Datos:

<html>
<body>
<form action=
"/ejemplocabeceras/servlet/ServletCabecerasRespuesta">

<table border="0">

<tr>
<td>
<input type="radio" name="accion" value="primo" selected>
Obtener ultimo numero primo
</td>
<td></td>
<td></td>
</tr>

<tr>
<td>
<input type="radio" name="accion" value="redirect">
Redirigir a una pagina
</td>
<td>
URL: 
<input type="text" name="url" value="http://www.ua.es">
</td>
<td></td>
</tr>

<tr>
<td>
<input type="radio" name="accion" value="error">
Mostrar pagina de error
</td>
<td>
Mensaje: 
<input type="text" name="mensaje" 
value="Error generado por el usuario">
</td>
<td>
Codigo:
<select name="codigoMensaje">
<option name="codigoMensaje" value="400">400</option>
<option name="codigoMensaje" value="401">401</option>
<option name="codigoMensaje" value="403">403</option>
<option name="codigoMensaje" value="404" selected>404
</option>
</select>
</td>
</tr>

<tr>
<td>
<input type="radio" name="accion" value="codigo">
Enviar codigo de error
</td>
<td>
Codigo:
<select name="codigo">
<option name="codigo" value="200">200</option>	
<option name="codigo" value="204">204</option>
<option name="codigo" value="404" selected>404</option>
</select>
</td>
<td></td>
</tr>

</table>

<input type="submit" value="Enviar Datos">

</form>
</body>
</html>

Aquí tenéis el WAR con los ejemplos. Copiadlo en el directorio webapps y probad cada ejemplo, respectivamente, con:

http://localhost:8080/ejemplocabeceras/inicioCabecerasPeticion.html
http://localhost:8080/ejemplocabeceras/inicioCabecerasRespuesta.html

 

2.4. Cookies y sesiones

2.4.1.Cookies

Una cookie es un objeto de tipo:

nombre = valor

donde se asigna un valor determinado (una cadena de texto) a una variable del nombre indicado. Dicho objeto es almacenado y recordado por el servidor web y el navegador durante un período de tiempo (indicado como un parámetro interno de la propia cookie). Así, se puede tener una lista de cookies con distintas variables y distintos valores, para almacenar información relevante para cada usuario (se tienen listas de cookies independientes para cada usuario).

En Javascript, por ejemplo, el objeto document.cookie contiene como valor una lista de la forma:

nombre1=valor1;nombre2=valor2;...;nombreN=valorN

donde se almacenan así los valores de las cookies que se tengan definidas.

Se pueden emplear cookies, entre otras cosas, para:

Los navegadores que trabajen con cookies pueden soportar hasta 20 cookies por servidor, de al menos 4 KB cada una. Los servlets que se ejecutan en un mismo servidor comparten las cookies.

A la hora de trabajar con cookies, debemos tener en cuenta que nuestro sitio web no debe depender de ellas, puesto que muchos navegadores y usuarios las deshabilitan para evitar problemas de privacidad y otras cuestiones.

Veremos ahora cómo trabajar con cookies desde servlets.

Enviar una cookie

Para crear una nueva cookie y enviarla, se siguen los pasos:

1. Crear la cookie

Las cookies se manejan con la clase Cookie. Se tiene el constructor:

public Cookie (String nombre, String valor)

que crea una cookie de nombre nombre, dándole el valor valor.

2. Establecer los atributos de la cookie

Una vez creada la cookie, podemos establecer los atributos que queramos, con los métodos de la clase Cookie. Por ejemplo, se tienen:

public void setComment(String comentario)
public void setMaxAge(int edad)
...

El primero asigna una cadena descriptiva sobre la cookie. El segundo indica cuántos segundos de vida tiene. Si es un valor negativo, se borrará la cookie cuando se cierre el navegador. Si el valor es 0, se borra la cookie instantáneamente, y si es positivo, se borrará la cookie cuando pasen los segundos indicados (si cerramos y volvemos a abrir el navegador dentro de ese tiempo, la cookie todavía persistirá). Se tienen otros métodos para establecer atributos de la cookie.

3. Enviar la cookie

Las cookies se añaden a la cabecera de la respuesta, y se envían así al cliente, mediante el método de HttpServletResponse:

public void addCookie (Cookie cookie)

Ejemplo

Vemos un ejemplo completo de envío de cookie:

public class MiServlet extends HttpServlet 
{ 
	public void doGet (HttpServletRequest request, 
	                   HttpServletResponse response) 
	throws ServletException, IOException
	{	
		Cookie miCookie = new Cookie ("nombre", "Pepe");
		miCookie.setMaxAge(120);
		response.addCookie(miCookie);
		PrintWriter out = response.getWriter();
		...
	}
}

Hay que tener en cuenta que las cookies son parte de la cabecera HTTP, con lo cual hay que enviarlas ANTES de escribir la respuesta (o antes de obtener el objeto Writer si lo queremos utilizar).

Obtener una cookie

Para obtener una cookie que envía el cliente se trabaja sobre la petición del cliente (HttpServletRequest), siguiendo los pasos:

1. Obtener todas las cookies

Obtenemos todas las cookies con el método getCookies() de la clase HttpServletRequest:

public Cookie[] getCookies()

Con esto se tiene un array con todas las cookies actuales para el usuario. Si no hay cookies el método devuelve null.

2. Obtener el valor de una cookie

Con lo anterior, para obtener el valor de una cookie simplemente recorremos el array de cookies buscando la que concuerde con el nombre que queramos. Pueden ser útiles los métodos de Cookie:

public String getName()
public String getValue()

El primero obtiene el nombre de la cookie, y el segundo el valor.

Ejemplo

Un ejemplo de uso, para obtener el nombre del usuario, guardado en la cookie "nombre":

public void doGet (HttpServletRequest request, 
                   HttpServletResponse response) 
throws ServletException, IOException
{	
	Cookie[] cookies = request.getCookies();
	String nombre;
	for (int i = 0; i < cookies.length; i++)
		if (cookies[i].getName().equals("nombre"))
			nombre = cookies[i].getValue();
}

Ejemplo

Aquí tenéis un WAR con un ejemplo de uso de cookies. El servlet ServletCookies cuenta el número de visitas a una página con una cookie que dura 3 minutos.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletCookies extends HttpServlet
{
   // Metodo para GET
	
   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response) 
   throws ServletException, IOException
   {
	response.setContentType("text/html");
	response.setHeader("Cache-Control", "no-cache");
		
	Cookie[] cookies = request.getCookies();
	Cookie contador = buscaCookie("contador", cookies);
		
	if (contador == null)
	{
	   // Creamos la cookie con el contador
			
	   Cookie cookie = new Cookie ("contador", "1");
	   cookie.setMaxAge(180);
	   response.addCookie(cookie);

	   // Mostramos el mensaje de primera visita

	   PrintWriter out = response.getWriter();
	   out.println ("<HTML>");			
	   out.println ("<BODY>");			
	   out.println ("Primera visita"); 
	   out.println ("<BR>");
	   out.println ("</BODY>");
	   out.println ("</HTML>");

	} else {
		
	   // Obtenemos el valor actual del contador
			
	   int cont = Integer.parseInt(contador.getValue());
	   cont++;
			
	   // Modificamos el valor de la cookie 
	   // incrementando el contador
			
	   Cookie cookie = new Cookie ("contador", "" + cont);
	   cookie.setMaxAge(180);
	   response.addCookie(cookie);

	   // Mostramos el numero de visitas

	   PrintWriter out = response.getWriter();
	   out.println ("<HTML>");
	   out.println ("<BODY>");
	   out.println ("Visita numero " + cont);
	   out.println ("<BR>");
	   out.println ("</BODY>");
	   out.println ("</HTML>");
	}		
   }	
	
   // Busca la cookie 'nombre' 
   // en el array de cookies indicado. 
   // Devuelve null si no esta
	
   private Cookie buscaCookie(String nombre, 
                              Cookie[] cookies)
   {
	if (cookies == null)
	   return null;
		
	for (int i = 0; i < cookies.length; i++)
	   if (cookies[i].getName().equals(nombre))
		return cookies[i];
		
	return null;
   }
}

Copiad el ejemplo en el directorio webapps de Tomcat, reiniciar el servidor y probadlo con:

http://localhost:8080/ejemplocookies/servlet/ServletCookies 

2.4.2. Seguimiento de sesiones

El seguimiento de sesiones es un mecanismo empleado por los servlets para gestionar un estado sobre las peticiones realizadas desde un mismo cliente (un mismo navegador) a lo largo de un período de tiempo determinado. Las sesiones se comparten por los servlets a los que accede un cliente (algo útil si queremos construir una aplicación basada en múltiples servlets).

Para utilizar el seguimiento de sesiones se tienen los pasos:

Obtener una sesión

El método getSession() del objeto HttpServletRequest obtiene una sesión de usuario.

public HttpSession getSession()
public HttpSession getSession(boolean crear)

El primer método obtiene la sesión actual, o crea una si no existe. Con el segundo método podemos establecer, mediante el flag booleano, si queremos crear una nueva si no existe (true) o no (false). Si la sesión es nueva, el método isNew() del HttpSession devuelve true, y la sesión no tiene ningún dato asociado. Deberemos ir añadiéndole datos tras crearla.

Para mantener la sesión de forma adecuada, debemos llamar a getSession() antes de que se escriba nada en la respuesta HttpServletResponse (y si utilizamos un Writer, debemos obtenerla antes de obtener el Writer, no antes de escribir datos).

Por ejemplo:

public class MiServlet extends HttpServlet 
{ 
	public void doGet (HttpServletRequest request, 
	                   HttpServletResponse response) 
	throws ServletException, IOException
	{	
		HttpSession sesion = request.getSession(true);
		...
		PrintWriter out = response.getWriter();
		...
	}
}

Guardar y obtener datos de la sesión

La interfaz HttpSession proporciona métodos que permiten almacenar y obtener datos de la sesión:

public String getId()
public Object getAttribute(String nombre)
public void   setAttribute(String nombre, Object valor)
public void   removeAttribute(String nombre)

que obtienen / establecen / eliminan, respectivamente, valores de atributos. Estos métodos eran getValue(), putValue() y removeValue() hasta la versión 2.2 de servlets. Se tienen además métodos como getAttributeNames() para obtener los nombres de los atributos que se tienen almacenados para la sesión, y otros métodos de utilidad en la clase HttpSession.

Por ejemplo:

public class MiServlet extends HttpServlet 
{ 
	public void doGet (HttpServletRequest request, 
	                   HttpServletResponse response) 
	throws ServletException, IOException
	{	
		HttpSession sesion = request.getSession(true);
		String nombreUsuario = 
		   (String)(sesion.getAttribute("nombre"));
		sesion.setAttribute("password", "secreto");
	}
}

El ejemplo lee el atributo "nombre" de la sesión, y establece el atributo "password" al valor "secreto".

Invalidar la sesión

Una sesión de usuario puede invalidarse manualmente, o automáticamente (dependiendo de dónde esté ejecutando el servlet). Esto implica eliminar el objeto HttpSession y sus valores de la memoria. Se tienen los métodos de HttpSession:

public int getMaxInactiveInterval()
public void setMaxInactiveInterval(int intervalo)
public void invalidate()

Para invalidarla automáticamente, la sesión expira cuando transcurre el tiempo indicado por el método getMaxInactiveInterval() entre dos accesos del cliente (en segundos). Se puede establecer dicho valor con setMaxInactiveInterval(...).

Para invalidar manualmente una sesión, se emplea el método invalidate() de la misma. Esto puede ser interesante por ejemplo en comercio electrónico: podemos mantener una sesión donde se vayan acumulando los productos que un usuario quiera comprar, e invalidar la sesión (borrarla) cuando el usuario compre los productos.

Por ejemplo:

public class MiServlet extends HttpServlet 
{ 
	public void doGet (HttpServletRequest request, 
	                   HttpServletResponse response) 
	throws ServletException, IOException
	{	
		HttpSession sesion = request.getSession(true);
		...
		sesion.invalidate();
		...
	}
}

Compatibilidad con los navegadores

Una alternativa para el seguimiento de sesiones consiste en la reescritura de URLs. Con esta técnica, se añaden como parámetros de la URL los datos relativos a la sesión actual, de forma que se van conservando entre las páginas.

El seguimiento de sesiones por defecto emplea cookies para almacenar el identificador de una sesión. Para poder utilizar seguimiento de sesiones con usuarios que accedan desde navegadores que no utilicen cookies, los servlets aplican automáticamente la reescritura de URLs cuando no se utilizan cookies. 

Para poder utilizar esto, debemos codificar todas las URLs que referenciemos. Para esto se emplean los métodos:

public String encodeURL(String url)
public String encodeRedirectURL(String url) 

El primero se emplea para asociar identificadores con URLs, se utilizará cuando pongamos urls en el contenido de la página que generamos. El segundo se utiliza para asociar identificadores con redirecciones. Lo emplearemos cuando utilicemos métodos sendRedirect(), para codificar la URL que se le pasa. Ambos devuelven la URL sobreescrita si la sobreescritura ha sido necesaria, o la misma URL si no ha sido necesario sobreescribir, dependiendo de si el navegador utiliza cookies (con lo que no es necesario incluir información de sesión en la URL), o no las utiliza (con lo que la información de sesión se introduce con estos métodos en la URL).

Por ejemplo:

public class MiServlet extends HttpServlet 
{ 
	public void doGet (HttpServletRequest request, 
	                   HttpServletResponse response) 
	throws ServletException, IOException
	{			
		...
		String url = response.encodeURL(
		   "http://localhost:8080/mipagina.html");
		out.println ("<a href=\"" + url + "\">...</a>");
		...
		String url2 = response.encodeRedirectURL(
		   "http://otrapagina.com");
		response.sendRedirect(url2);
	}
}

Ejemplo

Aquí tenéis un WAR con un ejemplo de uso de sesiones. El servlet ServletSesiones cuenta el número de visitas a una página en una sola sesión (en una sola ventana de navegador).

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ServletSesiones extends HttpServlet
{
   // Metodo para GET
	
   public void doGet(HttpServletRequest request, 
                     HttpServletResponse response) 
   throws ServletException, IOException
   {
	response.setContentType("text/html");
	response.setHeader("Cache-Control", "no-cache");
		
	HttpSession sesion = request.getSession();
	PrintWriter out = response.getWriter();

	if (sesion.isNew())
	{
	   // Mostramos un mensaje de primera visita

	   out.println ("<HTML>");			
	   out.println ("<BODY>");			
	   out.println ("Primera visita a la pagina");
	   out.println ("<BR>");
	   out.println ("</BODY>");			
	   out.println ("</HTML>");			
			
	   sesion.setAttribute("contador", new Integer(1));
			
	} else {

	   // Mostramos el numero de visitas 
	   // y actualizamos el contador
			
	   int contador = ((Integer)
	   (sesion.getAttribute("contador"))).intValue();
	   contador++;

	   out.println ("<HTML>");			
	   out.println ("<BODY>");			
	   out.println ("Visita numero " + 
			contador + 
			" a la pagina en esta sesion");
	   out.println ("<BR>");
	   out.println ("</BODY>");
	   out.println ("</HTML>");
			
	   sesion.setAttribute("contador", 
		               new Integer(contador));
	}		
   }	
}

Copiad el ejemplo en el directorio webapps de Tomcat, reiniciar el servidor y probadlo con:

http://localhost:8080/ejemplosesiones/servlet/ServletSesiones