«1. Обзор
Сервлеты — это простые классы Java, которые запускаются в контейнере сервлетов.
HTTP-сервлеты (особый тип сервлетов) являются первоклассными компонентами веб-приложений Java. API HTTP-сервлетов предназначен для обработки HTTP-запросов через типичный цикл запрос-обработка-ответ, реализованный в протоколах клиент-сервер.
Кроме того, сервлеты могут управлять взаимодействием между клиентом (обычно веб-браузером) и сервером, используя пары ключ-значение в виде параметров запроса/ответа.
Эти параметры можно инициализировать и привязать к области действия всего приложения (параметры контекста) и области действия, специфичной для сервлета (параметры сервлета).
В этом руководстве мы узнаем, как определить и получить доступ к контексту и параметрам инициализации сервлета.
2. Инициализация параметров сервлета
Мы можем определить и инициализировать параметры сервлета, используя аннотации и стандартный дескриптор развертывания — файл «web.xml». Стоит отметить, что эти два варианта не исключают друг друга.
Давайте подробно рассмотрим каждый из этих вариантов.
2.1. Использование аннотаций
Инициализация параметров сервлетов с помощью аннотаций позволяет хранить конфигурацию и исходный код в одном месте.
В этом разделе мы покажем, как определить и получить доступ к параметрам инициализации, привязанным к определенному сервлету, с помощью аннотаций.
Для этого мы реализуем наивный класс UserServlet, который собирает пользовательские данные через простую HTML-форму.
Во-первых, давайте посмотрим на файл JSP, который отображает нашу форму:
<!DOCTYPE html>
<html>
<head>
<title>Context and Initialization Servlet Parameters</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h2>Please fill the form below:</h2>
<form action="${pageContext.request.contextPath}/userServlet" method="post">
<label for="name"><strong>Name:</strong></label>
<input type="text" name="name" id="name">
<label for="email"><strong>Email:</strong></label>
<input type="text" name="email" id="email">
<input type="submit" value="Send">
</form>
</body>
</html>
Обратите внимание, что мы закодировали атрибут действия формы с помощью EL (язык выражений). Это позволяет ему всегда указывать на путь «/userServlet», независимо от расположения файлов приложения на сервере.
Выражение «${pageContext.request.contextPath}» устанавливает динамический URL-адрес для формы, который всегда относится к контекстному пути приложения.
Вот наша первоначальная реализация сервлета:
@WebServlet(name = "UserServlet", urlPatterns = {"/userServlet"}, initParams={
@WebInitParam(name="name", value="Not provided"),
@WebInitParam(name="email", value="Not provided")}))
public class UserServlet extends HttpServlet {
// ...
@Override
protected void doPost(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
forwardRequest(request, response, "/WEB-INF/jsp/result.jsp");
}
protected void processRequest(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("name", getRequestParameter(request, "name"));
request.setAttribute("email", getRequestParameter(request, "email"));
}
protected void forwardRequest(
HttpServletRequest request,
HttpServletResponse response,
String path)
throws ServletException, IOException {
request.getRequestDispatcher(path).forward(request, response);
}
protected String getRequestParameter(
HttpServletRequest request,
String name) {
String param = request.getParameter(name);
return !param.isEmpty() ? param : getInitParameter(name);
}
}
В этом случае мы определили два параметра инициализации сервлета, имя и адрес электронной почты, используя аннотации initParams и @WebInitParam.
Обратите внимание, что мы использовали метод getParameter() HttpServletRequest для извлечения данных из HTML-формы и метод getInitParameter() для доступа к параметрам инициализации сервлета.
Метод getRequestParameter() проверяет, являются ли параметры запроса name и email пустыми строками.
Если это пустые строки, то им присваиваются значения по умолчанию соответствующих параметров инициализации.
Метод doPost() сначала извлекает имя и адрес электронной почты, которые пользователь ввел в HTML-форму (если есть). Затем он обрабатывает параметры запроса и перенаправляет запрос в файл «result.jsp». запустите его, он должен сначала отобразить страницу HTML-формы.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>User Data</title>
</head>
<body>
<h2>User Information</h2>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
</body>
</html>
После того, как пользователь заполнил поля имени и адреса электронной почты и отправил форму, он выведет данные:
Если форма просто пуста, она отобразит параметры инициализации сервлета:
User Information
Name: the user's name
Email: the user's email
~ ~~ В этом примере мы показали, как определить параметры инициализации сервлета с помощью аннотаций и как получить к ним доступ с помощью метода getInitParameter().
User Information
Name: Not provided
Email: Not provided
2.2. Использование стандартного дескриптора развертывания
Этот подход отличается от подхода, использующего аннотации, поскольку он позволяет нам сохранять конфигурацию и исходный код изолированными друг от друга.
Чтобы продемонстрировать, как определить параметры инициализации сервлета с помощью файла «web.xml», давайте сначала удалим аннотации initParam и @WebInitParam из класса UserServlet:
Затем давайте определим параметры инициализации сервлета в файл «web.xml»:
@WebServlet(name = "UserServlet", urlPatterns = {"/userServlet"})
public class UserServlet extends HttpServlet { ... }
Как показано выше, определение параметров инициализации сервлета с помощью файла «web.xml» сводится к использованию \u003cinit-param\u003e, \u003cparam-name\u003e и Теги \u003cпараметр-значение\u003e.
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<servlet>
<display-name>UserServlet</display-name>
<servlet-name>UserServlet</servlet-name>
<init-param>
<param-name>name</param-name>
<param-value>Not provided</param-value>
</init-param>
<init-param>
<param-name>email</param-name>
<param-value>Not provided</param-value>
</init-param>
</servlet>
</web-app>
«Кроме того, можно определить столько параметров сервлета, сколько необходимо, если мы придерживаемся приведенной выше стандартной структуры.
Когда мы повторно развернем приложение на сервере и повторно запустим его, оно должно вести себя так же, как и версия, использующая аннотации.
3. Инициализация параметров контекста
Иногда нам нужно определить некоторые неизменяемые данные, которые должны быть глобально доступны и доступны через веб-приложение.
Из-за глобального характера данных мы должны использовать параметры инициализации контекста всего приложения для хранения данных, а не прибегать к аналогам сервлета.
Несмотря на то, что невозможно определить параметры инициализации контекста с помощью аннотаций, мы можем сделать это в файле «web.xml».
Предположим, что мы хотим предоставить некоторые глобальные значения по умолчанию для страны и провинции, где работает наше приложение.
Этого можно добиться с помощью нескольких параметров контекста.
Давайте соответствующим образом рефакторим файл «web.xml»:
На этот раз мы использовали теги \u003ccontext-param\u003e, \u003cparam-name\u003e и \u003cparam-value\u003e для определения контекстные параметры провинции и страны.
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<context-param>
<param-name>province</param-name>
<param-value>Mendoza</param-value>
</context-param>
<context-param>
<param-name>country</param-name>
<param-value>Argentina</param-value>
</context-param>
<!-- Servlet initialization parameters -->
</web-app>
Конечно, нам нужно реорганизовать класс UserServlet, чтобы он мог получать эти параметры и передавать их на страницу результатов.
Вот соответствующие разделы сервлета:
Обратите внимание на реализацию метода getContextParameter(), который сначала получает контекст сервлета через getServletContext(), а затем получает параметр контекста с помощью метода getInitParameter().
@WebServlet(name = "UserServlet", urlPatterns = {"/userServlet"})
public class UserServlet extends HttpServlet {
// ...
protected void processRequest(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.setAttribute("name", getRequestParameter(request, "name"));
request.setAttribute("email", getRequestParameter(request, "email"));
request.setAttribute("province", getContextParameter("province"));
request.setAttribute("country", getContextParameter("country"));
}
protected String getContextParameter(String name) {-
return getServletContext().getInitParameter(name);
}
}
Затем нам нужно реорганизовать файл «result.jsp», чтобы он мог отображать параметры контекста вместе с параметрами, специфичными для сервлета:
Наконец, мы можем повторно развернуть приложение и выполнить его один раз. снова.
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Province:</strong> ${province}</p>
<p><strong>Country:</strong> ${country}</p>
Если пользователь заполнит HTML-форму именем и адресом электронной почты, то он отобразит эти данные вместе с параметрами контекста:
В противном случае будут выведены параметры инициализации сервлета и контекста:
User Information
Name: the user's name
Email: the user's email
Province: Mendoza
Country: Argentina
Хотя пример надуман, он показывает, как использовать параметры инициализации контекста для хранения неизменяемых глобальных данных.
User Information
Name: Not provided
Email: Not provided
Province: Mendoza
Country: Argentina
Поскольку данные привязаны к контексту приложения, а не к конкретному сервлету, мы можем получить к ним доступ из одного или нескольких сервлетов, используя методы getServletContext() и getInitParameter().
4. Заключение
В этой статье мы изучили ключевые концепции параметров инициализации контекста и сервлета, а также способы их определения и доступа к ним с помощью аннотаций и файла «web.xml».
В течение некоторого времени в Java наблюдалась сильная тенденция избавляться от файлов конфигурации XML и переходить на аннотации, когда это возможно.
CDI, Spring, Hibernate и многие другие являются яркими примерами этого.
Тем не менее, нет ничего плохого в использовании файла «web.xml» для определения контекста и параметров инициализации сервлета.
Несмотря на то, что API сервлетов довольно быстро развивается в этом направлении, нам по-прежнему необходимо использовать дескриптор развертывания для определения параметров инициализации контекста.
Как обычно, все примеры кода, показанные в этой статье, доступны на GitHub.
«