В некоторых случаях требуется, чтобы все запросы к web-приложению направлялись к одному сервлету.

Web-приложение может состоять из большого количества сервлетов и JSP-страниц. Над этими компонентами приложения обычно приходится выполнять одинаковые действия, например протоколирование запросов, реализация политики безопасности, иногда нужно изменить объект-запрос перед его переадресацией другому сервлету или JSP. Так как необходимо выполнять одинаковые действия для всех компонентов web-приложения, то хотелось бы избежать дублирования кода и сосредоточить логику работы с запросами в одном месте.

Эта проблема решается с помощью шаблона Front Controller, который определяет единственный компонент (контроллер), отвечающий за обработку запросов.

Познакомиться поближе с паттерном Front Controller можно по следующим адресам:

web.xml – это место настройки сервлета на получение всех запросов web-приложения. В следующем листинге показано как использовать шаблон URL для направления всех запросов к сервлет-контейнеру.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
    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">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
 
    <servlet>
        <servlet-name>FirstServletInterceptor</servlet-name>
        <servlet-class>ru.topcode.testserv.FirstServlet</servlet-class>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>FirstServletInterceptor</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
 
    <servlet-mapping>
        <servlet-name>FirstServletInterceptor</servlet-name>
        <url-pattern>/servlets/*</url-pattern>
    </servlet-mapping>
</web-app>

Вам также необходимо удалить, изменить или закомментировать другие элементы servlet-mapping, которые позволяют обращаться к сервлетам в обход сервлета-контроллера. Если в web.xml включено какое-либо специфическое отображение, запросы к сервлету будут идти в обход сервлета-контроллера FirstServletInterceptor. Например:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
    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">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
 
    <servlet>
        <servlet-name>FirstServletInterceptor</servlet-name>
        <servlet-class>ru.topcode.testserv.FirstServlet</servlet-class>
    </servlet>
 
    <servlet>
        <servlet-name>SecondServlet</servlet-name>
        <servlet-class>ru.topcode.testserv.SecondServlet</servlet-class>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>FirstServletInterceptor</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
 
    <servlet-mapping>
        <servlet-name>FirstServletInterceptor</servlet-name>
        <url-pattern>/servlets/*</url-pattern>
    </servlet-mapping>
 
    <servlet-mapping>
        <servlet-name>SecondServlet</servlet-name>
        <url-pattern>/SecondServlet</url-pattern>
    </servlet-mapping>
</web-app>

В этом примере элемент servlet-mapping для SecondServlet позволяет использовать путь /SecondServlet к данному сервлету, в обход сервлета FirstServletInterceptor, поскольку путь /SecondServlet точнее соответствует шаблону URL /SecondServlet, нежели /*.

Обратите внимание на то, что запросы к статичному содержимому тоже перехватываются шаблоном /*. Эти запросы также направляются сервлет-контроллеру.

Чтобы протестировать все сказанное выше, нам понадобится два сервлета. Это FirstServletInterceptor – сервлет-контроллер:

package ru.topcode.testserv;
 
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 *
 * @author dmitrii.leontiev
 */
public class FirstServlet extends HttpServlet {
 
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
 
        // Устанавливаем MIME
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
 
        PrintWriter out = response.getWriter();
        out.println("<html><head>");
        out.println("<title>Отображение на сервлет всех запросов к web-приложению</title></head><body>");
        out.println("<h2>URL запроса:");
 
        out.println(request.getPathInfo() + "</h2>");
 
        out.println("</body></html>");
    }
}

И SecondServlet:

package ru.topcode.testserv;
 
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 *
 * @author dmitrii.leontiev
 */
public class SecondServlet extends HttpServlet {
 
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
 
        // Устанавливаем MIME
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
 
        PrintWriter out = response.getWriter();
        out.println("<html><head>");
        out.println("<title>Отображение на сервлет всех запросов к web-приложению</title></head><body>");
        out.println("Этот сервлет вызван в обход сервлета-контроллера");
 
        out.println("</body></html>");
    }
}

Теперь запустите web-приложение и перейдите по URL http://localhost:8084/servlets_jsp/argument1/argument2. Запрос будет передан сервлету FirstServlet, в котором выполняется конструкция request.getPathInfo(), которая в свою очередь возвращает URI запроса, начиная с /.

Если все сделано правильно, то в браузере вы должны увидеть следующую строку:

URL запроса: /argument1/argument2

Теперь перейдите по URL http://localhost:8084/servlets_jsp/SecondServlet. Вы должны увидеть строку

Этот сервлет вызван в обход сервлета-контроллера

На этом все. Мы научились применять шаблон проектирования Front Controller.