Сессия - это одна или несколько страниц, запрошенных клиентом на Web сайте во время определенного периода времени. Если вы покупаете продукты в режиме он-лайн, например, вы хотите, чтобы ваша сессия ограничивалась периодом от того момента, когда вы в первый раз добавили элемент в "свою корзину покупок" до момента, когда вы подтвердите выбор. Каждый добавленный вами элемент в корзину покупок будет результатом нового HTTP соединения, которое не знает о предыдущих соединениях или элементах в корзине покупок. Чтобы компенсировать этот недостаток информации, механизм обеспечивает спецификацию cookie, позволяющую вашему сервлету выполнить отслеживание сессии.

Объект сессии сервлета живет на серверной стороне коммуникационного канала; его целью является сбор полезных данных об этом клиенте, таких как перемещение клиента по сайту и взаимодействие с вашим Web сайтом. Эти данные могут относиться к текущей сессии и являться, например, элементами в корзине покупок, или это могут быть такие данные, как информация об авторизации, которая была введена клиентом при первом обращении к вашему Web сайту и поэтому ее не нужно вводить еще раз во время определенного набора транзакций.

Класс Session API сервлета использует класс Cookie, чтобы выполнить эту работу. Однако все объекты Session нуждаются в уникальном идентификаторе определенного рода, хранящемся у клиента и передающемся на сервер. Web сайты могут также использовать другие типы отслеживания сессии, но этот механизм будет более сложным для реализации, так как он не встроен в API сервлета (то есть, вы должны написать его руками, обработав ситуации, когда клиент отключает cookies).

Вот пример, который реализует отслеживание сессии с помощью API сервлета:

//: c15:servlets:SessionPeek.java
// Используем класс HttpSession.
// {Depends: j2ee.jar}
import java.io.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class SessionPeek extends HttpServlet {
  
public void service(HttpServletRequest req, HttpServletResponse res)
        
throws ServletException, IOException {
     
// Получаем объект Session до любой
      // посылки клиенту.
     
HttpSession session = req.getSession();
      res.setContentType
("text/html");
      PrintWriter out = res.getWriter
();
      out.println
("<HEAD><TITLE> SessionPeek ");
      out.println
(" </TITLE></HEAD><BODY>");
      out.println
("<h1> SessionPeek </h1>");
     
// Простой щетчик обращений для этой сессии.
     
Integer ival = (Integer) session.getAttribute("sesspeek.cntr");
     
if (ival == null)
        
ival = new Integer(1);
     
else
        
ival = new Integer(ival.intValue() + 1);
      session.setAttribute
("sesspeek.cntr", ival);
      out.println
("You have hit this page <b>" + ival + "</b> times.<p>");
      out.println
("<h2>");
      out.println
("Saved Session Data </h2>");
     
// Цикл по всем данным сессии:
     
Enumeration sesNames = session.getAttributeNames();
     
while (sesNames.hasMoreElements()) {
        
String name = sesNames.nextElement().toString();
         Object value = session.getAttribute
(name);
         out.println
(name + " = " + value + "<br>");
     
}
     
out.println("<h3> Session Statistics </h3>");
      out.println
("Session ID: " + session.getId() + "<br>");
      out.println
("New Session: " + session.isNew() + "<br>");
      out.println
("Creation Time: " + session.getCreationTime());
      out.println
("<I>(" + new Date(session.getCreationTime()) + ")</I><br>");
      out.println
("Last Accessed Time: " + session.getLastAccessedTime());
      out.println
("<I>(" + new Date(session.getLastAccessedTime())
           
+ ")</I><br>");
      out.println
("Session Inactive Interval: "
           
+ session.getMaxInactiveInterval());
      out.println
("Session ID in Request: " + req.getRequestedSessionId()
           
+ "<br>");
      out.println
("Is session id from Cookie: "
           
+ req.isRequestedSessionIdFromCookie() + "<br>");
      out.println
("Is session id from URL: "
           
+ req.isRequestedSessionIdFromURL() + "<br>");
      out.println
("Is session id valid: " + req.isRequestedSessionIdValid()
           
+ "<br>");
      out.println
("</BODY>");
      out.close
();
  
}
  
  
public String getServletInfo() {
     
return "A session tracking servlet";
  
}
}
// /:~

Внутри метода service( ) метод getSession( ) вызывается для объекта запроса, который возвращает объект Session, ассоциированный с этим запросом. Объект Session не посылается по сети, вместо этого он живет на сервере и ассоциируется с клиентом и его запросом.

getSession( ) существует в двух версиях: без параметра, как использовано здесь, и getSession(boolean). getSession(true) эквивалентно вызову getSession( ). Причина для булевского значения состоит в объявлении состояния, с которым вы хотите создать объект сессии, если он не найден. getSession(true) более желательный вызов, отсюда появилась версия getSession( ).

Объект Session, если он не новый, может дать нам детальную информацию о клиенте, взяв ее из предыдущих визитов. Если объект Session новый, то программа начнет собирать информацию об активности этого клиента в этом визите. Сбор этой информации о клиенте выполняется с помощью методов setAttribute( ) и getAttribute( ) объекта сессии.

java.lang.Object getAttribute(java.lang.String)
void setAttribute(java.lang.String name,  java.lang.Object value)

Объект Session использует простые пары имя-значение для загрузки информации. Имя является строкой, а значение может быть любым объектом, наследованным от java.lang.Object. SessionPeek следит за там, сколько раз клиент возвращался назад во время этой сессии. Это выполняется с помощью объекта Integer, называемого sesspeek.cntr. Если име не найдено, создается Integer со значением равным единице, в противном случае Integer создается с инкрементированным значением по сравнению с предыдущим сохраненным Integer. Новый Integer помещается в объект Session. Если вы используете тот же самый ключ в вызове setAttribute( ), то новый объект переписывает старый. Инкрементированный счетчик используется для отображения количества визитов клиента во время этой сессии.

getAttributeNames( ) имеет отношение к getAttribute( ) и setAttribute( ); он возвращает перечисление имен объектов, которые включены в объект Session. Цикл while в SessionPeek показывает этот метод в действии.

Вы можете удивиться, как долго хранится объект Session. Ответ зависит от контейнера сервлетов, который вы используете; обычно, по умолчанию, это 30 минут (1800 секунд), что вы можете увидеть из вызова метода getMaxInactiveInterval( ) в ServletPeek. Тесты могут воспроизводить разные результаты в зависмиости от контейнера сервлетов. Иногда объект Session может храниться всю ночь, но я никогда не видел случая, когда объект Session исчезал в течение времени меньшего, чем указано в интервале не активности. Вы можете попробовать путем установки интервала не активности с помощью метода setMaxInactiveInterval( ) в значение 5 секунд и посмотреть, останется ли ваш объект Session или он будет очищен в соответствующее время. Это может стать атрибутом, который вы захотите исследовать при выборе контейнера сервлетов.

Запуск примеров сервлета

Если вы еще не работали с Сервером приложений, который обрабатывает сервлеты Sun и JSP технологию для вас, вы можете загрузить Tomcat реализацию Java сервлетов и JSP, которая является бесплатной реализацией с открытыми исходниками, санкционированная Sun. Tomcat можно найти на jakarta.apache.org.

Следуйте инструкциям для установки Tomcat реализации, затем отредактируйте файл server.xml, чтобы указать место в вашем дереве директорий, где будут размещены ваши сервлеты. Когда вы запустите программу Tomcat, вы сможете протестировать ваши сервлеты.

Заключение

Это была только короткая интродукция в сервлеты; есть целые книги, посвещенные этой теме. Однако это введение должно дать вам достаточно мыслей, чтобы начать. Кроме того, многие мысли следующего раздела имеют обратную совместимость с сервлетами.