«1. Обзор

В этом руководстве мы создаем веб-приложение Java с использованием Servlet 3.0+.

Мы рассмотрим три аннотации — @WebServlet, @WebFilter и @WebListener — которые могут помочь нам удалить наши файлы web.xml.

2. Зависимость Maven

Чтобы использовать эти новые аннотации, нам нужно включить зависимость javax.servlet-api:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

3. Конфигурация на основе XML

До Servlet 3.0 мы ‘сконфигурирует веб-приложение Java в файле web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  version="2.5">
    <listener>
        <listener-class>com.baeldung.servlets3.web.listeners.RequestListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>uppercaseServlet</servlet-name>
        <servlet-class>com.baeldung.servlets3.web.servlets.UppercaseServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>uppercaseServlet</servlet-name>
        <url-pattern>/uppercase</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>emptyParamFilter</filter-name>
        <filter-class>com.baeldung.servlets3.web.filters.EmptyParamFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>emptyParamFilter</filter-name>
        <url-pattern>/uppercase</url-pattern>
    </filter-mapping>
</web-app>

Давайте начнем заменять каждый раздел конфигурации соответствующими аннотациями, представленными в Servlet 3.0.

4. Сервлеты

JEE 6 поставляется с Servlet 3.0, который позволяет нам использовать аннотации для определений сервлетов, сводя к минимуму использование файла web.xml для веб-приложения.

Например, мы можем определить сервлет и представить его с помощью аннотации @WebServlet

Давайте определим один сервлет для шаблона URL /uppercase. Это преобразует значение входного параметра запроса в верхний регистр:

@WebServlet(urlPatterns = "/uppercase", name = "uppercaseServlet")
public class UppercaseServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws IOException {
        String inputString = request.getParameter("input").toUpperCase();

        PrintWriter out = response.getWriter();
        out.println(inputString);
    }
}

Обратите внимание, что мы определили имя для сервлета (uppercaseServlet), на которое мы теперь можем ссылаться. Мы воспользуемся этим в следующем разделе.

С помощью аннотации @WebServlet мы заменяем разделы сервлета и отображения сервлета из файла web.xml.

5. Фильтры

Фильтр — это объект, используемый для перехвата запросов или ответов, выполнения задач предварительной или последующей обработки.

Мы можем определить фильтр с помощью аннотации @WebFilter.

Давайте создадим фильтр для проверки наличия входного параметра запроса:

@WebFilter(urlPatterns = "/uppercase")
public class EmptyParamFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
      FilterChain filterChain) throws IOException, ServletException {
        String inputString = servletRequest.getParameter("input");

        if (inputString != null && inputString.matches("[A-Za-z0-9]+")) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            servletResponse.getWriter().println("Missing input parameter");
        }
    }

    // implementations for other methods
}

С помощью аннотации @WebFilter мы заменяем разделы filter и filter-mapping из файла web.xml.

6. Слушатели

Нам часто нужно запускать действия, основанные на определенных событиях. Тут на помощь приходят слушатели. Эти объекты будут прослушивать событие и выполнять заданное нами поведение.

Как и ранее, мы можем определить слушателя с помощью аннотации @WebListener.

Давайте создадим прослушиватель, который учитывает каждый раз, когда мы выполняем запрос к серверу. Мы реализуем ServletRequestListener, прослушивающий ServletRequestEvents:

@WebListener
public class RequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent event) {
        HttpServletRequest request = (HttpServletRequest)event.getServletRequest();
        if (!request.getServletPath().equals("/counter")) {
            ServletContext context = event.getServletContext();
            context.setAttribute("counter", (int) context.getAttribute("counter") + 1);
        }
    }

    // implementations for other methods
}

Обратите внимание, что мы исключаем запросы к шаблону URL /counter.

С помощью аннотации @WebListener мы заменяем раздел слушателя из файла web.xml.

7. Сборка и запуск

Для тех, кто следит за этим, обратите внимание, что для тестирования мы добавили второй сервлет для конечной точки /counter, который просто возвращает атрибут контекста сервлета counter.

Итак, давайте использовать Tomcat в качестве сервера приложений.

Если мы используем версию maven-war-plugin до 3.1.0, нам нужно установить для свойства failOnMissingWebXml значение false.

Теперь мы можем развернуть наш файл .war на Tomcat и получить доступ к нашим сервлетам.

Давайте попробуем нашу конечную точку /uppercase:

curl http://localhost:8080/spring-mvc-java/uppercase?input=texttouppercase

TEXTTOUPPERCASE

И мы также должны посмотреть, как выглядит наша обработка ошибок:

curl http://localhost:8080/spring-mvc-java/uppercase

Missing input parameter

И, наконец, быстрый тест нашего слушателя:

curl http://localhost:8080/spring-mvc-java/counter

Request counter: 2

8. XML по-прежнему нужен

Даже со всеми функциями, представленными в Servlet 3.0, есть несколько случаев использования, когда нам все еще понадобится файл web.xml, среди них:

    Мы не можем определить порядок фильтрации с аннотациями — нам по-прежнему нужен раздел \u003cfilter-mapping\u003e, если у нас есть несколько фильтров, которые нужно применять в определенном порядке. Чтобы определить время ожидания сеанса, нам по-прежнему нужно использовать раздел \u003csession-config\u003e. нужен элемент \u003csecurity-role\u003e для авторизации на основе контейнера. И для указания приветственных файлов нам все еще понадобится раздел \u003cwelcome-file-list\u003e

Или, Servlet 3.0 также представил некоторую программную поддержку через ServletContainerInitializer, тоже, которые также могут заполнить некоторые из этих пробелов.

9. Заключение

В этом руководстве мы настроили веб-приложение Java без использования файла web.xml, используя эквивалентные аннотации.

Как всегда, исходный код этого руководства можно найти на GitHub. Кроме того, на GitHub можно найти приложение, использующее традиционный файл web.xml.

Для подхода на основе Spring перейдите к нашему руководству web.xml и Initializer with Spring.