Servlets y JSP

Hay un n�mero de problemas que vienen del hecho de que HTTP es un protocolo "sin estado". En particular, cuando estamos haciendo una compra on-line, es una molestia real que el servidor Web no puede recordar f�cilmente transaciones anteriores. Esto hace que las aplicaciones como las cartas de compras sean muy problem�ticas: cuando a�adimos una entrada en nuestra carta, �c�mo sabe el servidor que es realmente nuestra carta? Incluso si los servidores no retienen informaci�n contextual, todav�a tendr�amos problemas con comercio electr�nico. Cuando nos movemos desde la p�gina donde hemos especificado que queremos comprar (almacenada en un servidor Web normal) a la p�gina que toma nuestro n�mero de la tarjeta de cr�dito y la direcci�n de env�o (almacenada en un servidor seguro que usa SSL), �c�mo recuerda el servidor lo que hemos comprado?

Existen tres soluciones t�picas a este problema:

  1. Cookies. Podemos usar cookies HTTP para almacenar informaci�n sobre una sesi�n de compra, y cada conexi�n subsecuente puede buscar la sesi�n actual y luego extraer la informaci�n sobre esa sesi�n desde una localizaci�n en la m�quina del servidor. Esta es una excelente alternativa, y es la aproximaci�n m�s ampliamente utilizada. Sin embargo, aunque los servlets tienen un Interface de alto nivel para usar cookies, existen unos tediosos detalles que necesitan ser controlados:
    • Extraer el cookie que almacena el identificador de sesi�n desde los otros cookies (puede haber muchos, depu�s de todo),
    • Seleccionar un tiempo de expiraci�n apropiado para el cookie (las sesiones interrumpidas durante 24 horas probablemente deber�an ser reseteadas), y
    • Asociar la informaci�n en el servidor con el identificador de sesi�n (podr�a haber demasiada informaci�n que se almacena en el cookie, pero los datos sensibles como los n�meros de las tarjetas de cr�dito nunca deben ir en cookies).
  2. Reescribir la URL. Podemos a�adir alguna informaci�n extra al final de cada URL que identifique la sesi�n, y el servidor puede asociar ese identificador de sesi�n con los datos que ha almacenado sobre la sesi�n. Esta tambi�n es una excelente soluci�n, e incluso tiene la ventaja que funciona con navegadores que no soportan cookies o cuando el usuario las ha desactivado. Sin embargo, tiene casi los mismos problemas que los cookies, a saber, que los programas del lado del servidor tienen mucho proceso que hacer, pero tedioso. Adem�s tenemos que ser muy cuidadosos con que cada URL que le devolvamos al usuario tiene a�adida la informaci�n extra. Y si el usuario deja la sesi�n y vuelve mediante un bookmark o un enlace, la informaci�n de sesi�n puede perderse.
  3. Campos de formulario ocultos. Los formularios HTML tienen una entrada que se parece a esto: <INPUT TYPE="HIDDEN"�NAME="session"�VALUE="...">. Esto significa que, cuando el formulario se env�e, el nombre y el valor especificado se incluiran en los datos GET o POST. Esto puede usarse para almacenar informaci�n sobre la sesi�n. Sin embargo, tiene la mayor desventaja en que s�lo funciona si cada p�gina se genera din�micamente, ya que el punto negro es que cada sesi�n tiene un �nico identificador.

Los servlets proporcionan una soluci�n t�cnica. Al API HttpSession. Este es un interface de alto nivel construido sobre las cookies y la reescritura de URL. De hecho, muchos servidores, usan cookies si el navegador las soporta, pero autom�ticamente se convierten a reescritura de URL cuando las cookies no son soportadas o est�n desactivadas. Pero el autor de servlets no necesita molestarse con muchos detalles, no tiene que manipular expl�citamente las cookies o la informaci�n a�adida a la URL, y se les da autom�ticamente un lugar conveniente para almacenar los datos asociados con cada sesi�n.

.�2. El API de Seguimiento de Sesi�n

Usar sesiones en servlets es bastante sencillo, envolver la b�squeda del objeto sesi�n asociado con la petici�n actual, crear un nuevo objeto sesi�n cuando sea necesario, buscar la informaci�n asociada con una sesi�n, almacenar la informaci�n de una sesi�n, y descartar las sesiones completas o abandonadas.

.�2.1 Buscar el objeto HttpSession asociado con la petici�n actual.

Esto se hace llamando al m�todo getSession de HttpServletRequest. Si devuelve null, podemos crear una nueva sesi�n, pero es tan comunmente usado que hay una opci�n que crea autom�ticamente una nueva sesi�n si no existe una ya. S�lo pasamos true a getSession. As�, nuestro primer paso normalmente se parecer� a esto:

HttpSession session = request.getSession(true);

.�2.2 Buscar la Informaci�n Asociada con un Sesi�n.

Los objetos HttpSession viven en el servidor; son asociados autom�ticamente con el peticionario mediante un mecanismo detr�s de la escena como los cookies o la reescritura de URL. Estos objetos sesi�n tienen una estructura de datos interna que nos permite almacenar un n�mero de claves y valores asocidados. En la versi�n 2.1 y anteriores del API servlet, usamos getValue("key") para buscar un valor pr�viamente almacenado. El tipo de retorno es Object, por eso tenemos que forzarlo a un tipo m�s espec�fico de datos. El valor de retorno es null si no existe dicho atributo. En la versi�n 2.2 getValue est� obsoleto en favor de getAttribute, por el mejor nombrado correspondiente con setAttribute (el correspondiente para getValue es putValue, no setValue), y porque setAttribute nos permite usar un HttpSessionBindingListener asociado para monitorizar los valores, mientras que putValue no. Aqu� tenemos un ejemplo representativo, asumiendo que ShoppingCart es alguna clase que hemos definido nosotros mismos y que almacena infomaci�n de �tems para su venta:

HttpSession session = request.getSession(true);
  ShoppingCart previousItems = 
    (ShoppingCart)session.getValue("previousItems");
  if (previousItems != null) {
    doSomethingWith(previousItems);
  } else {
    previousItems = new ShoppingCart(...);
    doSomethingElseWith(previousItems);
  }

En la mayor�a de los casos, tenemos un nombre atributo espec�fico en mente, y queremos encontrar el valor (si existe) ya asociado con �l. Sin embargo, tambi�n podemos descubrir todos los nombres de atributos en una sesi�n dada llamando a getValueNames, que devuelve un array de String. La versi�n 2.2, usa getAttributeNames, que tienen un nombre mejor y que es m�s consistente ya que devuelve una Enumeration, al igual que los m�todos getHeaders y getParameterNames de HttpServletRequest.

Aunque los datos que fueron asociados expl�citamente con una sesi�n son la parte en la que debemos tener m�s cuidado, hay otras partes de informaci�n que son muy �tiles tambi�n.

  • getId. Este m�todo devuelve un identificador �nico generado para cada sesi�n. Algunas veces es usado como el nombre clave cuando hay un s�lo valor asociado con una sesi�n, o cuando se uso la informaci�n de logging en sesiones anteriores.
  • isNew. Esto devuelve true si el cliente (navegador) nunca ha visto la sesi�n, normalmente porque acaba de ser creada en vez de empezar una referencia a un petici�n de cliente entrante. Devuelve false para sesi�n preexistentes.
  • getCreationTime. Devuelve la hora, en milisegundos desde 1970, en la que se creo la sesi�n. Para obtener un valor �til para impresi�n, pasamos el valor al constructor de Date o al m�todo setTimeInMillis de GregorianCalendar.
  • getLastAccessedTime. Esto devuelve la hora, en milisegundos desde 1970, en que la sesi�n fue enviada por �ltima vez al cliente.
  • getMaxInactiveInterval. Devuelve la cantidad de tiempo, en segundos, que la sesi�n deber�a seguir sin accesos antes de ser invalidada autom�ticamente. Un valor negativo indica que la sesi�n nunca se debe desactivar.

.�2.3 Asociar Informaci�n con una Sesi�n

C�mo se describi� en la secci�n anterior, leemos la informaci�n asociada con una sesi�n usando getValue (o getAttribute en la versi�n 2.2 de las especificacioens Servlets). Observa que putValue reemplaza cualquier valor anterior. Algunas veces esto ser� lo que queremos pero otras veces queremos recuperar un valor anterior y aumentarlo. Aqu� tenemos un ejemplo:

HttpSession session = request.getSession(true);
  session.putValue("referringPage", request.getHeader("Referer"));
  ShoppingCart previousItems = 
    (ShoppingCart)session.getValue("previousItems");
  if (previousItems == null) {
    previousItems = new ShoppingCart(...);
  }
  String itemID = request.getParameter("itemID");
  previousItems.addEntry(Catalog.getEntry(itemID));
  // You still have to do putValue, not just modify the cart, since
  // the cart may be new and thus not already stored in the session.
  session.putValue("previousItems", previousItems);

.�3. Ejemplo: Mostrar Informaci�n de Sesi�n

Aqu� tenemos un sencillo ejemplo que genera una p�gina Web mostrando alguna informaci�n sobre la sesi�n actual. Tambi�n puedes El C�digo fuente.

package hall;

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

/** Simple example of session tracking. See the shopping
 *  cart example for a more detailed one.
 *  <P>
 *  Part of tutorial on servlets and JSP that appears at
 *  http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/
 *  1999 Marty Hall; may be freely used or adapted.
 */

public class ShowSession extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
    HttpSession session = request.getSession(true);
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String title = "Searching the Web";
    String heading;
    Integer accessCount = new Integer(0);;
    if (session.isNew()) {
      heading = "Welcome, Newcomer";
    } else {
      heading = "Welcome Back";
      Integer oldAccessCount =
        // Use getAttribute, not getValue, in version
        // 2.2 of servlet API.
        (Integer)session.getValue("accessCount"); 
      if (oldAccessCount != null) {
        accessCount =
          new Integer(oldAccessCount.intValue() + 1);
      }
    }
    // Use putAttribute in version 2.2 of servlet API.
    session.putValue("accessCount", accessCount); 
      
    out.println(ServletUtilities.headWithTitle(title) +
                "<BODY BGCOLOR=\"#FDF5E6\">\n" +
                "<H1 ALIGN=\"CENTER\">" + heading + "</H1>\n" +
                "<H2>Information on Your Session:</H2>\n" +
                "<TABLE BORDER=1 ALIGN=CENTER>\n" +
                "<TR BGCOLOR=\"#FFAD00\">\n" +
                "  <TH>Info Type<TH>Value\n" +
                "<TR>\n" +
                "  <TD>ID\n" +
                "  <TD>" + session.getId() + "\n" +
                "<TR>\n" +
                "  <TD>Creation Time\n" +
                "  <TD>" + new Date(session.getCreationTime()) + "\n" +
                "<TR>\n" +
                "  <TD>Time of Last Access\n" +
                "  <TD>" + new Date(session.getLastAccessedTime()) + "\n" +
                "<TR>\n" +
                "  <TD>Number of Previous Accesses\n" +
                "  <TD>" + accessCount + "\n" +
                "</TABLE>\n" +
                "</BODY></HTML>");

  }

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

Aqu� tenemos un resultado t�pico, despu�s de visitar la p�gina varias veces sin salir del navegador entre medias:

Resultado de visitar la página

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR