Utilizar Cookies

Las Cookies son una forma para que un servidor (o un servlet, como parte de un servidor) envíe información al cliente para almacenarla, y para que el servidor pueda posteriormente recuperar esos datos desde el cliente. Los servlet envían cookies al cliente añadiendo campos a las cabeceras de respuesta HTTP. Los clientes devuelven las cookies automáticamente añadiendo campos a las cabeceras de peticiones HTTP.

Cada cabecera de petición o respuesta HTTP es nombrada como un sólo valor. Por ejemplo, una cookie podría tener un nombre de cabecera BookToBuy con un valor 304qty1, indicando a la aplicación llamante que el usuario quiere comprar una copia del libro con el número 304 en el inventario. (Las cookies y sus valores son específicos de la aplicación).

Varias cookies pueden tener el mismo nombre. Por ejemplo, un servlet podría enviar dos cabeceras llamadas BookToBuy; una podría tener el valor anterior, 304qty1, mientras que la otra podría tener el valor 301qty3. Estas cookies podrían indicar que el usuario quiere comprar una copia del libro con el número 304 en el inventario y tres copias del libro con el número 301del inventario.

Además de un nombre y un valor, también se pueden proporcionar atributos opcionales como comentarios. Los navegadores actuales no siempre tratan correctamente a los atributos opcionales, por eso ten cuidado con ellos.

Un servidor puede proporcionar una o más cookies a un cliente. El software del cliente, como un navegador, se espera que pueda soportar veinte cookies por host de al menos 4 kb cada una.

Cuando se envía una cookie al cliente, el estándard HTTP/1.0 captura la página que no está en la caché. Actualmente, el javax.servlet.http.Cookie no soporta los controles de caché del HTTP/1.1.

Las cookies que un cliente almacena para un servidor sólo pueden ser devueltas a ese mismo servidor. Un servidor puede contener múltiples servlets; el ejemplo Duke's Bookstore está compuesto por varios servlets ejecutándose en un sólo servidor. Como las cookies son devueltas al servidor, los servlets que se ejecutan dentro de un servidor comparten las cookies. Los ejemplos de esta página ilustran esto mostrando como los servletsCatalogServlet y ShowCart trabajan con los mismos cookies.


Nota: Esta página tiene código que no forma parte del ejemplo Duke's Bookstore. Duke's Bookstore utilizaría código como el de esta página si utilizará cookies en vez de seguimiento de sesión para los pedidos de los clientes. Cómo las cookies no forman parte de Duke's Bookstore, piensa en los ejemplos de esta página como pseudo-código.

Para enviar una cookie:

  1. Ejemplariza un objeto Cookie.

  2. Selecciona cualquier atributo.

  3. Envia el cookie

Para obtener información de un cookie:

  1. Recupera todos los cookies de la petición del usuario.

  2. Busca el cookie o cookies con el nombre que te interesa, utiliza las técnicas de programación estándard.

  3. Obtén los balores de las cookies que hayas encontrado.

Crear un Cookie

El constructor de la clase javax.servlet.http.Cookie crea un cookie con un nombre inicial y un valor. Se puede cambiar el valor posteriormente utilizando el método setValue.

El nombre del cookie debe ser un token HTTP/1.1. Los tokens son strings que contienen uno de los caracteres especiales liestados en RFC 2068. (Strings alfanuméricos cualificados como tokens.) Además, los nombres que empiezan con el carácter dollar ("$") están reservados por RFC 2109.

El valor del cookie puede ser cualquier string, aunque no está garantizado que los valores null funcionen en todos los navegadores. Además, si enviamos una cookie que cumpla con las especificaciones originales de las cookies de Netscape, no se deben utilizar carácteres blancos ni ninguno de estos caracteres:

[ ] ( ) = , "" / ? @ : ;

Si nuestro servlet devuelve una respuesta al usuario con un Writer, debemos crear la cookie antes de acceder a Writer. (Porque las cookies se envían al cliente como una cabecera, y las cabeceras deben escribirse antes de acceder al Writer.)

Si el CatalogServlet utilizará cookies para seguir la pista de una hoja de pedido, el servlet podría crear las cookies de esta forma:

    public void doGet (HttpServletRequest request,
                       HttpServletResponse response)
	throws ServletException, IOException
    {
        BookDBServlet database = (BookDBServlet)
            getServletConfig().getServletContext().getServlet("bookdb");

        // Check for pending adds to the shopping cart
        String bookId = request.getParameter("Buy");

        //If the user wants to add a book, remember it by adding a cookie
        if (bookId != null) {
            Cookie getBook = new Cookie("Buy", bookId);
            ...
        }

	// set content-type header before accessing the Writer
        response.setContentType("text/html");

        // now get the writer and write the data of the response
	PrintWriter out = response.getWriter();
        out.println("<html>" +
                    "<head><title> Book Catalog </title></head>" + ...);
        ...
    }

Seleccionar los Atributos de un Cookie

La clase Cookie proporciona varios métodos para seleccionar los valores del cookie y sus atributos. La utilización de estos métodos es correcta, están explicados en el javadoc para la clase Cookie.

El siguiente ejemplo selecciona el campo comment del cookie CatalogServlet. Este campo describe el propósito del cookie.

    public void doGet (HttpServletRequest request,
                       HttpServletResponse response)
	throws ServletException, IOException
    {
        ...
        //If the user wants to add a book, remember it by adding a cookie
        if (values != null) {
            bookId = values[0];
            Cookie getBook = new Cookie("Buy", bookId);
            getBook.setComment("User wants to buy this book " +
                               "from the bookstore.");
        }
        ...
    }
También se puede seleccionar la caducidad del cookie. Este atributo es útil, por ejemplo, para borrar un cookie. De nuevo, si Duke's Bookstore utilizará cookies para su hoja de pedidos, el ejemplo podría utilizar este atributo para borrar un libro de la hoja de pedido. El usuario borra un libro de la hoja de pedidos en el ShowCartServlet; su código se podría parecer a esto:
    public void doGet (HttpServletRequest request,
                       HttpServletResponse response)
	throws ServletException, IOException
    {
	...
        /* Handle any pending deletes from the shopping cart */
        String bookId = request.getParameter("Remove");
        ...        
        if (bookId != null) {
            // Find the cookie that pertains to the book to remove
            ...
                    // Delete the cookie by setting its maximum age to zero
                    thisCookie.setMaxAge(0);
            ...
        }
            
	// also set content type header before accessing the Writer
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        //Print out the response
        out.println("<html> <head>" +
                    "<title>Your Shopping Cart</title>" + ...);

Enviar Cookies

Las cookies se envían como cabeceras en la respuesta al cliente, se añaden con el método addCookie de la clase HttpServletResponse. Si estamos utilizando un Writer para devolver texto, debemos llamar a addCookie antes de llamar al método getWriter de HttpServletResponse.

Continuando con el ejemplo de CatalogServlet, aquí está el código para enviar la cookie:

    public void doGet (HttpServletRequest request,
                       HttpServletResponse response)
	throws ServletException, IOException
    {
        ...
        //If the user wants to add a book, remember it by adding a cookie
        if (values != null) {
            bookId = values[0];
            Cookie getBook = new Cookie("Buy", bookId);
            getBook.setComment("User has indicated a desire " +
                               "to buy this book from the bookstore.");
            response.addCookie(getBook);
        }
        ...
    }

Recuperar Cookies

Los clientes devuelven las cookies como campos añadidos a las cabeceras de petición HTTP. Para recuperar una cookie, debemos recuperar todas las cookies utilizando el método getCookies de la clase HttpServletRequest.

El método getCookies devuelve un array de objetos Cookie, en el que podemos buscar la cookie o cookies que querramos. (Recuerda que distintas cookies pueden tener el mismo nombre, para obtener el nombre de una cookie, utiliza su método getName.)

Para continuar con el ejemplo ShowCartServlet:

    public void doGet (HttpServletRequest request,
                       HttpServletResponse response)
	throws ServletException, IOException
    {
	...

        /* Handle any pending deletes from the shopping cart */
        String bookId = request.getParameter("Remove");
        ...        
        if (bookId != null) {
            
            // Find the cookie that pertains to the book to remove
            Cookie[] cookies = request.getCookies();
            ...

            // Delete the book's cookie by setting its maximum age to zero
            thisCookie.setMaxAge(0);
        }
            
	// also set content type header before accessing the Writer
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        //Print out the response
        out.println("<html> <head>" +
                    "<title>Your Shopping Cart</title>" + ...);

Obtener el valor de una Cookie

Para obtener el valor de una cookie, se utiliza el método getValue.
    public void doGet (HttpServletRequest request,
                       HttpServletResponse response)
	throws ServletException, IOException
    {
        ...
        /* Handle any pending deletes from the shopping cart */
        String bookId = request.getParameter("Remove");
        ...        
        if (bookId != null) {
            // Find the cookie that pertains to that book
            Cookie[] cookies = request.getCookies();
            for(i=0; i < cookies.length; i++) {
                Cookie thisCookie = cookie[i];
                if (thisCookie.getName().equals("Buy") &&
                    thisCookie.getValue().equals(bookId)) {

                    // Delete the cookie by setting its maximum age to zero
                    thisCookie.setMaxAge(0);
                }
            }
        }
            
	// also set content type header before accessing the Writer
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        //Print out the response
        out.println("<html> <head>" +
                    "<title>Your Shopping Cart</title>" + ...);

Ozito