Куки это способ сервера (или сервлета, как части сервера) посылать клиенту на хранение часть информации, чтобы потом получать эту информацию от клиента. Сервлеты посылают куки клиенту, добавляя код в ответе в HTTP заголовки. Клиенты автоматически возвращают куки, добавляя код в запросы в HTTP заголовках.

Каждый заголовок HTTP запроса и ответа именован и имеет единственное значение. Например, у куки могло бы быть имя BookToBuy со значением 304qty1, сообщающим вызываемому приложению, что пользователь хочет купить книгу с номером 304 количеством 1 единица. (Куки и их значения задаются конкретным приложением.)

Множественные куки могут иметь одно и тоже имя. Например, сервлет может отправить две куки, имя которых BookToBuy; одна может иметь величину приведенную выше, 304qty1, а вторая — значение 301qty3. Эти куки будут означать, что пользователь хочет купить одну книгу с номером 304, и три книги с номером 301.

В добавление к имени и значению, Вы также можете предоставить необязательные элементы, такие, как комментарии. Текущий броузер может не всегда правильно воспринимать необязательные параметры, поэтому Вы не должны полагаться на них.

Сервер может отправлять одну или более куки для клиента. Предполагается, что программа клиента, как web броузер, должна поддерживать 20 куки на хост, и как минимум четыре килобайта каждая.

Когда Вы посылаете куки клиенту, стандартный кэш HTTP/1.0 не будет кэшировать страницу. На данный момент, javax.servlet.http.Cookie не поддерживает HTTP/1.1 модули кэширования.

Куки, которые клиент сохранил для сервера, возвращаются клиентом только этому серверу. Сервер может включать множество сервлетов; пример Duke's Bookstore сделан из нескольких сервлетов работающих на одном сервере. Потому как куки возвращаются серверу, сервлеты работающие на этом сервере совместно используют эти куки. Пример в этом разделе иллюстрирует это на сервлетах CatalogServlet и ShowCart, работающих с одними куками.

Примечание: В этом разделе приводится пример не являющийся частью примера Duke's Bookstore. Пример Duke's Bookstore мог бы использовать код использованный в этом уроке, если бы использовал куки вместо отслеживания сессии для определения заказа клиента. Поскольку куки не являются частью примера Duke's Bookstore, будем считать этот код псевдокодом.

Чтобы отправить куки,

  1. Создайте объект Cookie
  2. Установите любые атрибуты
  3. Отправьте куки

Чтобы извлечь информацию из куки,

  1. Запросите все куки из пользовательского запроса
  2. Найдите куки с именем, которое Вас интересует, используя стандартные программные операции
  3. Получите значения куки, которые были найдены
 

Создание куки

Конструктор класса javax.servlet.http.Cookie создает куки с начальным именем и значением. Вы можете изменить значение куки позже, вызвав метод setValue.

Имя куки должно быть HTTP/1.1 токен. Токены это строки, не содержащие специальных символов перечисленных в документе RFC 2068. (буквенно-численные строки квалифицируемые как токены.) В добавление, имена, начинающиеся со знака доллар $ зарезервированы документом RFC 2109

Значением строки может быть любая строка, хотя не гарантируется, что значение null, будет одинаково работать на всех броузерах. В добавление, если Вы отправляете куки, которая подчиняется оригинальной спецификации куки Нетскейпа, не используйте пробелы или ниже приведенные символы:

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

Если сервлет возвращает ответ пользователю, используя Writer, создавайте куки, прежде чем обратитесь к Writer. (Поскольку куки отправляются к клиенту как заголовок, заголовки должны быть прописаны, прежде чем произойдет обращение к Writer.)

Если бы сервлет CatalogServlet использовал куки для того, чтобы проследить заказ клиента, он бы создавал бы их следующим образом:

public void doGet (HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    // Смотрим есть ли покупки в корзине
    String bookId = request.getParameter("Buy");
    // Если пользователь хочет добавить книгу, запоминаем это добавляя куки
    if (bookId != null) {
        Cookie getBook = new Cookie("Buy", bookId);
        ...
    }
    // прежде чем начать вывод, устанавливаем тип содержимого
    response.setContentType("text/html");
    // теперь выводим данные ответа
    PrintWriter out = response.getWriter();
    out.println("<html>" 
            + "<head><title> Book Catalog </title></head>" 
            + ...);
    ...
}
 

Установка атрибутов куки

Класс Cookie обеспечивает набор методов для установки параметров куки и ее атрибутов. Использование этих методов поступательно; они описаны в документации для класса Cookie.

Следующий пример показывает, как установить комментарий для куки CatalogServlet. Комментарий описывает назначение куки.

public void doGet (HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    ...
    // Если пользователь хочет добавить книгу, запоминаем это добавляя куки
    if (values != null) {
        bookId = values[0];
        Cookie getBook = new Cookie("Buy", bookId);
        getBook.setComment("User wants to buy this book " 
                + "from the bookstore.");
    }
    ...
}

Вы также можете установить максимальный возраст куки. Этот атрибут полезен, например, для удаления куки. И опять, если бы Duke's Bookstore использовал куки для того, чтобы проследить заказ клиента, то, например, использовал бы данный атрибут для удаления книги из заказа пользователя. Пользователь удаляет книгу из корзины для покупок в сервлете ShowCartServlet; код бы мог выглядеть следующим образом:

public void doGet (HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    ...
    // Управление удалением из корзины
    String bookId = request.getParameter("Remove");
    ...        
    if (bookId != null) {
        // Находим куки которая отвечает за удаляемую книгу
        ...
        // Удаляем куки устанавливая ее возраст равным нулю
        thisCookie.setMaxAge(0);
        ...
    }
    // Прежде чем начать вывод, устанавливаем тип содержимого
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    // Выводим ответ
    out.println("<html><head>" 
            + "<title>Your Shopping Cart</title>" 
            + ...);
    ...
}
 

Отправка куки

Куки отправляются как заголовки ответа клиенту; они добавляются с помощью метода addCookie класса HttpServletResponse. Если Вы используете Writer для отправки куки пользователю, Вы должны использовать метод addCookie, прежде чем вызвать метод getWriter класса HttpServletResponse.

Продолжая пример CatalogServlet, приводим следующий код для отправки куки:

public void doGet (HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    ...
    //Если пользователь хочет добавить книгу, запоминаем это добавляя куки
    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);
    }
    ...
}
 

Запрашивание куки

Клиенты возвращают куки как поля, добавленные в HTTP заголовок запроса. Чтобы запросить какую-либо куки, Вам надо запросить все куки, используя метод getCookies из класса HttpServletRequest.

Метод getCookies возвращает массив объектов Cookie, который Вы можете просмотреть, чтобы найти необходимую вам куки или множество куки. (Запомните, что множественные куки имеют одно и тоже имя. Чтобы получить имя куки используйте ее метод getName.)

Продолжая пример сервлета ShowCartServlet:

public void doGet (HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    ...
    // Управление удалением из корзины
    String bookId = request.getParameter("Remove");
    ...        
    if (bookId != null) {
        //находим куки которая отвечает за удаляемую книгу
        Cookie[] cookies = request.getCookies();
        ...
        //Удаляем куки устанавливая ее возраст равным нулю
        thisCookie.setMaxAge(0);
    }
    // Прежде чем начать вывод, устанавливаем тип содержимого
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    // Выводим ответ
    out.println("<html><head>" 
            + "<title>Your Shopping Cart</title>" 
            + ...);
    ...
}
 

Получение значения куки

Чтобы получить значение закладки, используйте ее метод getValue. Продолжая пример сервлета ShowCartServlet:

public void doGet (HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    ...
    // Управление удалением из корзины
    String bookId = request.getParameter("Remove");
    ...        
    if (bookId != null) {
        //Находим куки соответствующую данной книге
        Cookie[] cookies = request.getCookies();
        for(i=0; i = thisCookie.getValue().equals(bookId); i++) {
            // Удаляем куки устанавливая ее возраст равным нулю
            thisCookie.setMaxAge(0);
        }
    }
    // Прежде чем начать вывод, устанавливаем тип содержимого
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    // Выводим ответ
    out.println("<html><head>" 
            + "<title>Your Shopping Cart</title>" 
            + ...);
    ...
}