В некоторых случаях требуется, чтобы все запросы к web-приложению направлялись к одному сервлету.
Web-приложение может состоять из большого количества сервлетов и JSP-страниц. Над этими компонентами приложения обычно приходится выполнять одинаковые действия, например протоколирование запросов, реализация политики безопасности, иногда нужно изменить объект-запрос перед его переадресацией другому сервлету или JSP. Так как необходимо выполнять одинаковые действия для всех компонентов web-приложения, то хотелось бы избежать дублирования кода и сосредоточить логику работы с запросами в одном месте.
Эта проблема решается с помощью шаблона Front Controller, который определяет единственный компонент (контроллер), отвечающий за обработку запросов.
Познакомиться поближе с паттерном Front Controller можно по следующим адресам:
- http://java.sun.com/blueprints/patterns/FrontController.html
- http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html
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.


Pingback: Отображение запросов на контроллер с сохранением отображений сервлетов | Java EE Dev
#1 by Artos on 28 Сентябрь 2009 - 0:29
Quote
Объясните начинающему зачем это все нужно? Если для решения следующих задач(протоколирование запросов, реализация политики безопасности) можно или даже нужно и лучше использовать listeners и filters?