Перейти к основному содержимому

Контекст и параметры инициализации сервлета

· 7 мин. чтения

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 .