- •Раздел 12. Веб-сервера
- •12.2. Стандарт cgi
- •Раздел 13. Технология Java Servlet
- •Пример сервлета
- •Компиляция сервлетов
- •Структура веб-модуля
- •Запуск сервлета
- •Архив веб-модуля
- •13.2. Структура и жизненный цикл сервлета
- •Работа сервлетов в многопоточной среде
- •13.3. Основные классы Servlet api Класс HttpServletRequest (запрос)
- •Класс HttpServletResponse (ответ)
- •Класс HttpServlet (сервлет)
- •Класс ServletContext (взаимодействие с сервлет-контейнером)
- •13.4. Cookies и сессии
- •13.5. Отладка сервлетов
- •Раздел 14. Технология JavaServer Pages
- •14.1. Введение в jsp
- •14.2. Жизненный цикл jsp-страниц
- •Действия
- •14.4. Язык выражений
- •Предопределенные объекты
- •14.5. Библиотеки тегов
- •Раздел 14. Технология JavaServer Pages
- •14.1. Введение в jsp
- •14.2. Жизненный цикл jsp-страниц
- •Действия
- •14.4. Язык выражений
- •Предопределенные объекты
- •14.5. Библиотеки тегов
Класс HttpServlet (сервлет)
Кроме методов doGet, doPost, doHead, service, init, destroy, которые реализуются самими разработчиками, сервлеты включают и некоторые другие методы.
String getInitParameter(String name) — метод позволяет получить параметр инициализации сервлета, который может быть указан в web.xml следующим образом:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>MyServletClass</servlet-class>
<init-param>
<param-name>name</param-name>
<param-value>value</param-value>
</init-param>
</servlet>
Где name и value — это название и значение параметра (параметров может быть несколько). В качестве параметров инициализации могут выступать, к примеру, каталог, где сервлет должен хранить данные, или параметры соединения с СУБД (адрес сервера, имя пользователя, пароль и проч.).
Список всех параметров можно получить с помощью метода getInitParameterNames().
void log(String msg) — добавляет сообщение в журнал веб-сервера (в Tomcat журналы размещаются в каталоге logs).
ServletContext getServletContext() — возвращает объект ServletContext, с помощью которого можно взаимодействовать с сервлет-контейнером.
Класс ServletContext (взаимодействие с сервлет-контейнером)
String getServerInfo() — название и версия сервлет-контейнера.
String getRealPath(String path) — полный путь к файлу по его относительному пути в веб-модуле. Например, вызов сервлетом метода getServletContext().getRealPath("/WEB-INF/web.xml") вернет полный путь к дескриптору веб-модуля.
RequestDispatcher getRequestDispatcher(String path) — возвращает объект RequestDispatcher, с помощью которого в ответ сервлета можно включить результат работы другого сервлета или статический файл веб-модуля. В параметрах указывается путь (сервлета или файла) относительно корня веб-модуля.
Пример сервлета, который включает в ответ меню, которое располагается по адресу /menu.html (путь относительно каталога веб-модуля):
public class HomeServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html; charset=windows-1251");
PrintWriter out = res.getWriter();
out.println("<html><body>");
req.getRequestDispatcher("/menu.html").include(req, res);
out.println("<h1>Заголовок страницы</h1>");
out.println("Тело страницы.);
out.println("</body></html>");
}
}
Ресурс с адресом /menu.html может быть просто HTML-файлом, который расположен в корне веб-модуля, а может быть и сервлетом (если сервлету назначить адрес /menu.html в web.xml).
13.4. Cookies и сессии
HTTP — это протокол без сохранения состояния (stateless), т. к. для получения каждой веб-страницы клиент создает новое сетевое соединение с сервером. И поэтому сервер не может автоматически распознать — новый запрос выполнен тем же пользователем или уже другим.
Cookies
Cookies — это небольшое количество текстовой информации, которую веб-сервер посылает браузеру и которую браузер затем посылает в неизменном виде серверу при посещении этого же веб-сайта. Т. е. веб-приложение, таким образом, может сохранить некоторую информацию на стороне клиента.
Cookies веб-сервер отправляет в HTTP-заголовке «Set-Cookie», а браузер возвращает их в HTTP-заголовке «Cookie». В cookies веб-приложение может хранить:
-
индивидуальные настройки пользователя (например, город, который выбрал пользователь, чтобы автоматически отображать прогноз погоды в этом городе при следующих визитах пользователя);
-
имя пользователя и e-mail (например, на форуме, чтобы каждый раз не указывать их заново);
-
идентификатор сессии (некоторая строка, которая генерируется автоматически веб-приложением при первом посещении веб-страницы и затем используется для идентификации посетителя при следующих запросах).
Идентификатор сессии и cookies можно сравнить с картой клиента магазина: её вручают клиенту при одном из первых посещений, а при следующих визитах покупатель предоставляет её, чтобы сотрудники магазина могли идентифицировать покупателя и записать информацию о покупках и предоставить скидку.
Хранение в cookies идентификатора сессии сейчас является распространенной практикой при создании веб-ресурсов, которые «помнят» своих посетителей. И часто в cookies хранят только идентификатор сессии пользователя, а все настройки, ассоциированные с этим пользователем, хранят на стороне сервера.
Например, в онлайн-магазине для каждого пользователя на сервере может храниться его текущая корзина товаров. Т. к. веб-браузер каждый раз посылает на сервер идентификатор сессии, то веб-приложение знает, какая конкретно «корзина» относится к текущему пользователю.
Этот же подход используется для аутентификации: после ввода верного имени пользователя и пароля, сервер «запоминает», что пользователь с текущим идентификатором сессии зашел с указанным именем пользователя. Этот метод безопаснее, чем хранить в cookies имя пользователя и пароль и каждый раз передавать их на веб-сервер.
Добавить cookies в HTTP-заголовок можно методом addHeader, но удобнее это выполнить методом addCookie, например:
Cookie cityCookie = new Cookie("city", "krasnojarsk");
cityCookie.setMaxAge(60*60*24*365); // время хранения cookie браузером
response.addCookie(userCookie); // неявная установка заголовка Set-Cookie
Если не установить явно срок хранения cookies, то веб-браузер будет их хранить до закрытия окна браузера.
Получить cookies сервлет может с помощью метода getCookies у объекта-запроса:
String city = null; Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (int i=0; i < cookies.length; i++) {
if (cookies[i].getName().equals("city")) {
city = cookies[i].getValue();
break;
}
}
}
На самом деле, напрямую с cookies обычно не работают, т. к. Servlet API поддерживает более удобный механизм сессий, основанный на cookies и прозрачном использовании идентификаторов сессий.
Сессии
В Servlet API сессия — это объект, в котором можно хранить данные, ассоциированные с текущим пользователем. Для идентификации пользователя используются идентификаторы сессии, которые автоматически генерируются и сохраняются в cookies. Причем разработчику не нужно самому заботиться ни об идентификаторах сессии, ни о cookies. Он просто сохраняет данные в сессию и когда нужно извлекает их оттуда.
Использовать сессии в сервлетах просто:
-
Получаем ссылку на объект-сессию:
HttpSession session = request.getSession();
-
Сохраняем информацию (указывается имя и значение):
session.setAttribute("city", city);
-
Получаем информацию, сохраненную ранее для этого пользователя:
String city = (String) session.getAttribute("city");
-
При необходимости удаляем информацию:
session.removeAttribute("city");
session.invalidate(); // удаляет все данные сессии текущего пользователя
Метод getSession() извлекает из cookies идентификатор сессии клиента, а затем использует этот идентификатор для поиска объекта HttpSession в служебной таблице ранее созданных объектов HttpSession. Если идентификатора в cookies еще нет, то создается новый пустой объект HttpSession, генерируется случайный идентификатор, экземпляр HttpSession сохраняется в таблице сессий и клиенту отсылается cookies с его идентификатором.
Пример сервлета, работающего с сессиями:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
req.setCharacterEncoding("UTF-8");
res.setContentType("text/html; charset=UTF-8");
String name = req.getParameter("name");
HttpSession session = req.getSession();
if (name == null)
name = (String)session.getAttribute("user_name");
else
session.setAttribute("user_name", name);
PrintWriter out = res.getWriter();
if (name == null)
out.printf("<form action='%s'>Ваше имя: <input name=name>" +
"<input type=submit></form>", req.getRequestURI());
else
out.println("<h1>Здравствуйте, " + name + "!</h1>");
}
}
Данный сервлет запрашивает имя пользователя, после чего выводит приветствие. При следующих визитах сервлет выводит приветствие вместе с сохраненным именем, уже не запрашивая имя повторно.
Аналогичным образом, в объект-сессию можно сохранять корзину товаров, имя пользователя (логин) и т. д.