Пример учебника по фильтрам Java Servlet

Java Servlet Filter используется для перехвата запроса клиента и выполнения предварительной обработки. Он также может перехватывать ответ и выполнять пост-обработку перед отправкой клиенту в веб-приложении. Это четвертая статья в серии учебников по веб-приложениям. Вам может быть интересно ознакомиться с предыдущими статьями.

  1. Java веб-приложение
  2. Учебник по Java Servlet
  3. Управление сеансами в Servlet

Servlet Filter

В этой статье мы рассмотрим Servlet Filter в Java. Мы рассмотрим различные способы использования фильтра сервлета, как создать фильтр и узнаем о его использовании с помощью простого веб-приложения.

  1. Зачем у нас есть Servlet Filter?

  2. Интерфейс Servlet Filter

  3. Аннотация Servlet WebFilter

  4. Настройка фильтра Servlet в web.xml

  5. Пример фильтра Servlet для ведения журнала и проверки сеанса

  6. Зачем у нас есть Servlet Filter?

    В последней статье мы узнали, как управлять сессией в веб-приложении, и если мы хотим удостовериться, что ресурс доступен только при условии действительной сессии пользователя, мы можем достичь этого, используя атрибуты сеанса сервлета. Подход прост, но если у нас много сервлетов и JSP, то его будет сложно поддерживать из-за избыточного кода. Если мы захотим изменить имя атрибута в будущем, нам придется изменить все места, где у нас есть аутентификация сеанса. Вот почему у нас есть фильтр сервлета. Фильтры сервлетов – это модульные компоненты Java, которые мы можем использовать для перехвата и обработки запросов перед их отправкой в сервлеты и ответа после завершения кода сервлета и перед отправкой ответа контейнером обратно клиенту. Некоторые общие задачи, которые мы можем выполнять с помощью фильтров сервлетов, включают:

    • Регистрация параметров запроса в файлы журнала.
    • Аутентификация и авторизация запросов к ресурсам.
    • Форматирование тела или заголовка запроса перед его отправкой в сервлет.
    • Сжатие данных ответа, отправляемых клиенту.
    • Изменение ответа путем добавления некоторых файлов cookie, информации заголовка и т. д.

    Как я упоминал ранее, фильтры сервлетов модульные и настраиваются в файле дескриптора развертывания (web.xml). Сервлеты и фильтры ничего не знают друг о друге, и мы можем добавлять или удалять фильтр сервлета, просто редактируя web.xml. Мы можем иметь несколько фильтров для одного ресурса, и мы можем создать цепочку фильтров для одного ресурса в web.xml. Мы можем создать фильтр сервлета, реализовав интерфейс javax.servlet.Filter.

  7. Интерфейс фильтра Servlet

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

    1. void init(FilterConfig paramFilterConfig) – Когда контейнер инициализирует фильтр, вызывается этот метод. Этот метод вызывается только один раз в жизненном цикле фильтра, и мы должны инициализировать любые ресурсы в этом методе. FilterConfig используется контейнером для предоставления параметров инициализации и объекта контекста сервлета фильтру. Мы можем бросить ServletException в этом методе.
    2. doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain) – Этот метод вызывается контейнером каждый раз, когда ему нужно применить фильтр к ресурсу. Контейнер предоставляет ссылки на объекты запроса и ответа фильтру в качестве аргумента. FilterChain используется для вызова следующего фильтра в цепочке. Это отличный пример Шаблон Цепочка обязанностей.
    3. void destroy() – Когда контейнер выгружает экземпляр фильтра, он вызывает метод destroy(). Этот метод, где мы можем закрыть все ресурсы, открытые фильтром. Этот метод вызывается только один раз в жизни фильтра.
  8. Аннотация Servlet WebFilter

    javax.servlet.annotation.WebFilter был введен в Servlet 3.0, и мы можем использовать эту аннотацию для объявления фильтра сервлета. Мы можем использовать эту аннотацию для определения параметров инициализации, имени и описания фильтра, сервлетов, шаблонов URL и типов диспетчеров, к которым применяется фильтр. Если вы часто вносите изменения в конфигурации фильтра, лучше использовать web.xml, потому что это не потребует перекомпиляции класса фильтра. Читать: Руководство по аннотациям Java

  9. Конфигурация фильтра Servlet в web.xml

    Мы можем объявить фильтр сервлета в файле web.xml следующим образом.

    <filter>
      <filter-name>RequestLoggingFilter</filter-name> <!-- обязательно -->
      <filter-class>com.journaldev.servlet.filters.RequestLoggingFilter</filter-class> <!-- обязательно -->
      <init-param> <!-- опционально -->
      <param-name>test</param-name>
      <param-value>testValue</param-value>
      </init-param>
    </filter>
    

    Мы можем сопоставить фильтр с классами сервлетов или url-шаблонами следующим образом.

    <filter-mapping>
      <filter-name>RequestLoggingFilter</filter-name> <!-- обязательно -->
      <url-pattern>/*</url-pattern> <!-- обязательно либо url-pattern, либо servlet-name -->
      <servlet-name>LoginServlet</servlet-name>
      <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
    

    Примечание: При создании цепочки фильтров для сервлета контейнер сначала обрабатывает url-шаблоны, а затем имена сервлетов, так что, если вам нужно убедиться, что фильтры выполняются в определенном порядке, обратите особое внимание при определении сопоставления фильтров. Фильтры сервлетов обычно используются для запросов клиентов, но иногда мы хотим применить фильтры также с помощью RequestDispatcher, в этом случае мы можем использовать элемент dispatcher, возможные значения: REQUEST, FORWARD, INCLUDE, ERROR и ASYNC. Если dispatcher не определен, то он применяется только к запросам клиентов.

  10. Пример фильтра сервлета для ведения журнала и проверки сеанса

In our **servlet filter example**, we will create filters to log request cookies and parameters and validate session to all the resources except static HTMLs and LoginServlet because it will not have a session. We will create a dynamic web project **ServletFilterExample** whose project structure will look like the below image. [![Servlet Filter Example, Java Filter](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Example-Project.png)](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Example-Project.png) login.html is the entry point of our application where the user will provide the login id and password for authentication. login.html code:

```



























Login Page


Username:
Password:
``` LoginServlet is used to authenticate the request from the client for login. ``` package com.journaldev.servlet.session; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Servlet implementation class LoginServlet */ @WebServlet("/LoginServlet") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 1L; private final String userID = "admin"; private final String password = "password"; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // получение параметров запроса для идентификатора пользователя и пароля String user = request.getParameter("user"); String pwd = request.getParameter("pwd"); if(userID.equals(user) && password.equals(pwd)){ HttpSession session = request.getSession(); session.setAttribute("user", "Pankaj"); // установка сеанса на истечение через 30 минут session.setMaxInactiveInterval(30*60); Cookie userName = new Cookie("user", user); userName.setMaxAge(30*60); response.addCookie(userName); response.sendRedirect("LoginSuccess.jsp"); }else{ RequestDispatcher rd = getServletContext().getRequestDispatcher("/login.html"); PrintWriter out= response.getWriter(); out.println("Either user name or password is wrong."); rd.include(request, response); } } } ``` When the client is authenticated, it's forwarded to LoginSuccess.jsp LoginSuccess.jsp code: ``` <%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> Login Success Page <% // разрешение доступа только если сеанс существует String user = (String) session.getAttribute("user"); String userName = null; String sessionID = null; Cookie[] cookies = request.getCookies(); if(cookies !=null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("user")) userName = cookie.getValue(); if(cookie.getName().equals("JSESSIONID")) sessionID = cookie.getValue(); } } %>

Hi <%=userName %>, Login successful. Your Session ID=<%=sessionID %>


User=<%=user %>
Checkout Page
``` Notice that there is no session validation logic in the above JSP. It contains a link to another JSP page, CheckoutPage.jsp. CheckoutPage.jsp code: ``` <%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> Login Success Page <% String userName = null; String sessionID = null; Cookie[] cookies = request.getCookies(); if(cookies !=null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("user")) userName = cookie.getValue(); } } %>

Hi <%=userName %>, do the checkout.


``` LogoutServlet is invoked when a client clicks on the Logout button in any of the JSP pages. ``` package com.journaldev.servlet.session; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Servlet implementation class LogoutServlet */ @WebServlet("/LogoutServlet") public class LogoutServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); Cookie[] cookies = request.getCookies(); if(cookies != null){ for(Cookie cookie : cookies){ if(cookie.getName().equals("JSESSIONID")){ System.out.println("JSESSIONID="+cookie.getValue()); break; } } } // аннулирование сеанса, если он существует HttpSession session = request.getSession(false); System.out.println("User="+session.getAttribute("user")); if(session != null){ session.invalidate(); } response.sendRedirect("login.html"); } } ``` Now we will create logging and authentication servlet filter classes. ``` package com.journaldev.servlet.filters; import java.io.IOException; import java.util.Enumeration; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; /** * Servlet Filter implementation class RequestLoggingFilter */ @WebFilter("/RequestLoggingFilter") public class RequestLoggingFilter implements Filter { private ServletContext context; public void init(FilterConfig fConfig) throws ServletException { this.context = fConfig.getServletContext(); this.context.log("RequestLoggingFilter initialized"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; Enumeration params = req.getParameterNames(); while(params.hasMoreElements()){ String name = params.nextElement(); String value = request.getParameter(name); this.context.log(req.getRemoteAddr() + "::Request Params::{"+name+"="+value+"}"); } Cookie[] cookies = req.getCookies(); if(cookies != null){ for(Cookie cookie : cookies){ this.context.log(req.getRemoteAddr() + "::Cookie::{"+cookie.getName()+","+cookie.getValue()+"}"); } } // передача запроса по цепочке фильтров chain.doFilter(request, response); } public void destroy() { // мы можем закрыть здесь ресурсы } } ``` ``` package com.journaldev.servlet.filters; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebFilter("/AuthenticationFilter") public class AuthenticationFilter implements Filter { private ServletContext context; public void init(FilterConfig fConfig) throws ServletException { this.context = fConfig.getServletContext(); this.context.log("AuthenticationFilter initialized"); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; String uri = req.getRequestURI(); this.context.log("Requested Resource::"+uri); HttpSession session = req.getSession(false); if(session == null && !(uri.endsWith("html") || uri.endsWith("LoginServlet"))){ this.context.log("Unauthorized access request"); res.sendRedirect("login.html"); }else{ // передача запроса по цепочке фильтров chain.doFilter(request, response); } } public void destroy() { // закрытие любых ресурсов здесь } } ``` Notice that we are not authenticating any HTML page or LoginServlet. Now we will configure these filters mapping in the web.xml file. ``` ServletFilterExample login.html RequestLoggingFilter com.journaldev.servlet.filters.RequestLoggingFilter AuthenticationFilter com.journaldev.servlet.filters.AuthenticationFilter RequestLoggingFilter /* REQUEST AuthenticationFilter /* ``` Now when we will run our application, we will get response pages like below images. [![Servlet Filter Example](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login-450x141.png)](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login.png) [![Servlet Filter, Java Filter](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login-Success-450x229.png)](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Login-Success.png) [![Servlet Filter Tutorial, Java Servlet Filter](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Checkout-450x181.png)](https://journaldev.nyc3.cdn.digitaloceanspaces.com/2013/08/Servlet-Filter-Checkout.png) If you are not logged in and try to access any JSP page, you will be forwarded to the login page. In the server log file, you can see the logs written by servlet filters as well as servlets. ``` Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A} Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/ Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log INFO: Unauthorized access request Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A} Aug 13, 2013 1:06:07 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/login.html Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Request Params::{pwd=password} Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Request Params::{user=admin} Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,B7275762B8D23121152B1270D6EB240A} Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/LoginServlet Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56} Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin} Aug 13, 2013 1:06:43 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/LoginSuccess.jsp Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56} Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin} Aug 13, 2013 1:06:52 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/CheckoutPage.jsp Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56} Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin} Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/LogoutServlet JSESSIONID=8BDF777933194EDCAC1D8F1B73633C56 User=Pankaj Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56} Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin} Aug 13, 2013 1:07:00 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/login.html Aug 13, 2013 1:07:06 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56} Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin} Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/LoginSuccess.jsp Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log INFO: Unauthorized access request Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{JSESSIONID,8BDF777933194EDCAC1D8F1B73633C56} Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log INFO: 0:0:0:0:0:0:0:1%0::Cookie::{user,admin} Aug 13, 2013 1:07:07 AM org.apache.catalina.core.ApplicationContext log INFO: Requested Resource::/ServletFilterExample/login.html ```

Вот и все для фильтра сервлета в Java. Это одна из важных функций веб-приложений Java EE, и мы должны использовать ее для общих задач, выполняемых различными сервлетами. В будущих сообщениях мы рассмотрим прослушиватели сервлетов и куки. Обновление: После получения множества запросов на загружаемый проект, я прикрепил его к сообщению, загрузите его по ссылке ниже.

Загрузить пример проекта фильтра сервлета

Посмотрите следующую статью в серии о Слушателе Servlet. Обновление Struts 2 использует Servlet Filter для перехвата запросов клиента и перенаправления их на соответствующие классы действий, которые называются Struts 2 Interceptors. Ознакомьтесь с Учебником для начинающих по Struts 2.

Source:
https://www.digitalocean.com/community/tutorials/java-servlet-filter-example-tutorial