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 doGet(
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);
}
}
В этом случае мы определили два параметра инициализации сервлета, name
и email
, используя initParams
и аннотации @WebInitParam
.
Обратите внимание, что мы использовали метод getParameter()
HttpServletRequest для извлечения данных из HTML-формы и метод getInitParameter()
для доступа к параметрам инициализации сервлета.
Метод getRequestParameter()
проверяет, являются ли параметры запроса name
и email
пустыми строками.
Если это пустые строки, то им присваиваются значения по умолчанию соответствующих параметров инициализации.
Метод doPost()
сначала извлекает имя и адрес электронной почты, которые пользователь ввел в HTML-форму (если есть). Затем он обрабатывает параметры запроса и перенаправляет запрос в файл «result.jsp»
:
<!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>
Если мы развернем наше типовое веб-приложение на сервере приложений, таком как Apache Tomcat, Oracle GlassFish или JBoss WidlFly , и запустим его, оно должно сначала отобразить страницу HTML-формы.
Как только пользователь заполнит поля имени
и адреса электронной почты
и отправит форму, он выведет данные:
User Information
Name: the user's name
Email: the user's email
Если форма просто пуста, она отобразит параметры инициализации сервлета:
User Information
Name: Not provided
Email: Not provided
В этом примере мы показали, как определить параметры инициализации сервлета с помощью аннотаций и как получить к ним доступ с помощью метода g
etInitParameter()
.
2.2. Использование стандартного дескриптора развертывания
Этот подход отличается от того, что использует аннотации, так как позволяет нам держать конфигурацию и исходный код изолированными друг от друга .
Чтобы продемонстрировать, как определить параметры сервлета инициализации с помощью файла «web.xml»
, давайте сначала удалим аннотации initParam
и @WebInitParam
из класса UserServlet
:
@WebServlet(name = "UserServlet", urlPatterns = {"/userServlet"})
public class UserServlet extends HttpServlet { ... }
Далее определим параметры инициализации сервлета в файле «web.xml»
:
<?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>
Как показано выше, определение параметров инициализации сервлета с помощью файла «web.xml»
сводится к использованию тегов <init-param>,
<param-name>
и <param-value> .
Кроме того, можно определить столько параметров сервлета, сколько необходимо, если мы придерживаемся приведенной выше стандартной структуры.
Когда мы повторно развертываем приложение на сервере и повторно запускаем его, оно должно вести себя так же, как и версия, использующая аннотации.
3. Инициализация параметров контекста
Иногда нам нужно определить некоторые неизменяемые данные, которые должны быть глобально доступны и доступны через веб-приложение.
Из-за глобального характера данных мы должны использовать параметры инициализации контекста всего приложения для хранения данных, а не прибегать к аналогам сервлета .
Несмотря на то, что невозможно определить параметры инициализации контекста с помощью аннотаций, мы можем сделать это в файле «web.xml»
.
Предположим, что мы хотим предоставить некоторые глобальные значения по умолчанию для страны и провинции, где работает наше приложение.
Мы можем сделать это с помощью нескольких параметров контекста.
Давайте соответствующим образом рефакторим файл «web.xml»
:
<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>
На этот раз мы использовали теги <context-param>, <param-name>
и <param-value>
для определения параметров контекста провинции
и страны .
Конечно, нам нужно реорганизовать класс UserServlet
, чтобы он мог получать эти параметры и передавать их на страницу результатов.
Вот соответствующие разделы сервлета:
@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);
}
}
Обратите внимание на реализацию метода getContextParameter()
, который сначала получает контекст сервлета через getServletContext(),
а затем получает параметр контекста с помощью метода getInitParameter()
.
Затем нам нужно реорганизовать файл «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 .