JavaWeb 中 Filter过滤器

打印 上一主题 下一主题

主题 872|帖子 872|积分 2626

Filter过滤器


每博一文案
  1. 师傅说:人生无坦途,累是必须的背负,看多了,人情人暖,走遍了离合聚散,有时会
  2. 在心里对自己说,我想,我是真的累了,小时候有读不完的书,长大后有赚不尽的力。
  3. 白天在外要奋斗打拼,把心事都藏起来,笑脸相迎,做一个合格的员工,晚上回家要照顾家人。
  4. 把家务都打理的井井有条,做一个称职的伴侣,习惯了所有事情,自己扛,习惯了所有委屈自己消化,
  5. 有时候莫名的低落,什么话都不想说,只想一个静静的发呆,有时会突然的烦躁,什么事都不想做,
  6. 只想让自己好好的放松,偶尔也会向往过一份属于自己的生活。
  7. 没有那么多责任,要背负只做自己想做的事,累了就停下类休息吧,烦了就给自己放个假吧。
  8. 这个世上没有铁打的身体,该休息时就得休息。
  9. 这个世上没有坚强的心灵,该哭泣时就该哭泣。
  10. 看看碧海蓝天,听听轻歌曼舞,会会知己老友,品品清茶,美酒,生活本就可以多姿多彩。
  11. 人生说到底,活的是心气,为累过,方知闲,为苦过,方知甜,随缘自在,勿忘心安,便是活着的最美状态。
  12.                                        ——————《一禅心灵庙语1》
复制代码
@
目录

1. Filter 过滤器的概述


在一个比较复杂的Web应用程序中,通常都有很多URL映射,对应的,也会有多个Servlet来处理URL。
我们考察这样一个论坛应用程序:
  1.             ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
  2.                /             ┌──────────────┐
  3.             │ ┌─────────────>│ IndexServlet │ │
  4.               │              └──────────────┘
  5.             │ │/signin       ┌──────────────┐ │
  6.               ├─────────────>│SignInServlet │
  7.             │ │              └──────────────┘ │
  8.               │/signout      ┌──────────────┐
  9. ┌───────┐   │ ├─────────────>│SignOutServlet│ │
  10. │Browser├─────┤              └──────────────┘
  11. └───────┘   │ │/user/profile ┌──────────────┐ │
  12.               ├─────────────>│ProfileServlet│
  13.             │ │              └──────────────┘ │
  14.               │/user/post    ┌──────────────┐
  15.             │ ├─────────────>│ PostServlet  │ │
  16.               │              └──────────────┘
  17.             │ │/user/reply   ┌──────────────┐ │
  18.               └─────────────>│ ReplyServlet │
  19.             │                └──────────────┘ │
  20.              ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
复制代码
各个Servlet设计功能如下:

  • IndexServlet:浏览帖子;
  • SignInServlet:登录;
  • SignOutServlet:登出;
  • ProfileServlet:修改用户资料;
  • PostServlet:发帖;
  • ReplyServlet:回复。
其中,ProfileServlet、PostServlet和ReplyServlet都需要用户登录后才能操作,否则,应当直接跳转到登录页面。
我们可以直接把判断登录的逻辑写到这3个Servlet中,但是,同样的逻辑重复3次没有必要,并且,如果后续继续加Servlet并且也需要验证登录时,还需要继续重复这个检查逻辑。
为了把一些公用逻辑从各个Servlet中抽离出来,JavaEE的Servlet规范还提供了一种Filter组件,即过滤器,它的作用是,在HTTP请求到达Servlet之前,可以被一个或多个Filter预处理,类似打印日志、登录检查等逻辑,完全可以放到Filter中。



什么是 Filter 过滤器:

  • Filter 过滤器它是 JavaWeb 的三大组件之一。
    三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器
  • Filter 过滤器它是 JavaEE 的规范。也就是接口
  • Filter 过滤器它的作用是:拦截请求,过滤响应。
拦截请求常见的应用场景有:
1.权限检查 2.日记操作 3.事务管理 ……等等
一般情况下,都是在过滤器当中编写公共代码。提高代码的复用性.
2. Filter 过滤器的编写


  • 第一步:编写一个Java类实现一个接口:jarkata.servlet.Filter。并且实现这个接口当中所有的方法。




  • init( )方法:在Filter对象第一次被创建之后调用,并且只调用一次。与Servlet中的init()方法类似,filter中的init()方法用于初始化过滤器。开发者可以在init()方法中完成与构造方法类似的初始化功能。如果初始化代码中要用到FilterConfig对象,则这些初始化代码只能在filter的init()方法中编写,而不能在构造方法中编写。 default 是接口中的一个默认方法,基于 jdk8 新特性,默认方法可以不用重写,如果有需要也是可以重写的.
  1. public default void init(FilterConfig filterConfig) throws ServletException {}
复制代码

  • doFilter( )方法:只要用户发送一次请求,则执行一次。发送N次请求,则执行N次。在这个方法中编写过滤规则。需要注意的是,服务器响应的时候,该方法也是会被执行的。doFilter方法类似于Servlet接口的service()方法。当客户端请求目标资源时,容器会筛选出符合标签中的filter,并按照声明的顺序依次调用这些filter的doFilter()方法。doFilter()方法有多个参数,其中参数request和response为Web服务器或filter链中的上一个filter传递过来的请求和响应对象。参数chain代表当前filter链的对象,只有当前filter对象中的doFilter()方法内部需要调用FilterChain对象的doFilter方法时,才能把请求交付给filter链中的下一个filter或目标程序处理。这个是抽象方法,必须重写。
  1. public void doFilter(ServletRequest request, ServletResponse response,
  2.             FilterChain chain) throws IOException, ServletException;
复制代码

  • destroy( )方法:在Filter对象被释放/销毁之前调用,并且只调用一次。 filter中的destroy()方法Servlet中的destroy()作用类似,在Web服务器卸载filter对象之前被调用,用于释放被filter对象打开的资源。 default 是接口中的一个默认方法,基于 jdk8 新特性,默认方法可以不用重写,如果有需要也是可以重写的.
  1. public default void destroy() {}
复制代码
  1. package com.RainbowSea.filter;
  2. import jakarta.servlet.Filter;
  3. import jakarta.servlet.FilterChain;
  4. import jakarta.servlet.FilterConfig;
  5. import jakarta.servlet.ServletException;
  6. import jakarta.servlet.ServletRequest;
  7. import jakarta.servlet.ServletResponse;
  8. import java.io.IOException;
  9. public class TestFilter implements Filter {
  10.     @Override
  11.     public void init(FilterConfig filterConfig) throws ServletException {
  12.         System.out.println("TestFilter 中的 init() 方法 初始化 执行了");
  13.     }
  14.     @Override
  15.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  16.         System.out.println("TestFilter 中的 doFilter() 方法执行了");
  17.     }
  18.     @Override
  19.     public void destroy() {
  20.         System.out.println("TestFilter 中的 destroy() 方法 销毁 执行了");
  21.     }
  22. }
复制代码

  • 第二步:在web.xml文件中对 Filter进行配置。这个配置和 Servlet很像。
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
  5.          version="5.0">
  6.     <filter>
  7.         
  8.         <filter-name>filter</filter-name>
  9.         
  10.         <filter-class>com.RainbowSea.filter.TestFilter</filter-class>
  11.     </filter>
  12.     <filter-mapping>
  13.         <filter-name>filter</filter-name>
  14.         
  15.         <url-pattern>/a.do</url-pattern>
  16.     </filter-mapping>
  17.    
  18.    
  19. </web-app>
复制代码
如下是关于: Filter的所有的 web.xml 中的配置属性信息:
标签作用指定一个过滤器用于为过滤器指定一个名称,该元素的内容不能为空用于指定过滤器的完整的限定类名用于为过滤器指定初始化参数为的子参数,用于指定参数的名称用于设置一个filter所负责拦截的资源为子元素,用于设置filter的注册名称。该值必须是在元素中声明过的过滤器的名称用于设置filter所拦截的请求路径用于指定过滤器所拦截的Servlet名称执行效果:



如果Servlet版本大于3.0,也可以使用注解 @WebFilter()的方式来配置filter。

如下:
  1. package com.RainbowSea.filter;
  2. import jakarta.servlet.Filter;
  3. import jakarta.servlet.FilterChain;
  4. import jakarta.servlet.FilterConfig;
  5. import jakarta.servlet.ServletException;
  6. import jakarta.servlet.ServletRequest;
  7. import jakarta.servlet.ServletResponse;
  8. import jakarta.servlet.annotation.WebFilter;
  9. import java.io.IOException;
  10. @WebFilter("/a.do")
  11. public class TestFilter implements Filter {
  12.     @Override
  13.     public void init(FilterConfig filterConfig) throws ServletException {
  14.         System.out.println("TestFilter 中的 init() 方法 初始化 执行了");
  15.     }
  16.     @Override
  17.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  18.         System.out.println("TestFilter 中的 doFilter() 方法执行了");
  19.     }
  20.     @Override
  21.     public void destroy() {
  22.         System.out.println("TestFilter 中的 destroy() 方法 销毁 执行了");
  23.     }
  24. }
复制代码
如下是关于:@WebFilter() 的属性的说明:
属性类型是否必须说明asyncSupportedboolean否指定filter是否支持异步模式dispatcherTypesDispatcherType[]否指定filter对哪种方式的请求进行过滤filterNameString否filter名称initParamsWebInitParam[]否配置参数displayNameString否filter显示名servletNamesString[]否指定对哪些Servlet进行过滤urlPatterns/valueString[]否两个属性作用相同,指定拦截的路径web.xml可以配置的filter属性都可以通过@WebServlet的方式进行配置。不过一般不推荐使用注解方式来配置filter,因为如果存在多个过滤器,使用web.xml配置filter可以控制过滤器的执行顺序,如果使用了注解方式,则不可以这样做了。该 Filter 执行顺序该文章的后面会详细说明,所以请大家,耐心阅读。谢谢。
3. Filter 过滤器的执行过程解析




当用户向服务器发送request请求时,服务器接受该请求,并将请求发送到第一个过滤器中进行处理。如果有多个过滤器,则会依次经过filter2,filter3,…,filter n。接着调用Servlet中的service()方法,调用完毕后,按照与进入时相反的顺序,从过滤器filter n开始,依次经过各个过滤器,直到过滤器filter 1.最终将处理后的结果返回给服务器,服务器再反馈给用户。
filter进行拦截的方式也很简单,在HttpServletRequest到达Servlet之前,filter拦截客户的HttpServletRequest,根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。在HttpServletRequest到达客户端之前,拦截HttpServletRequest,根据需要检查HttpServletRequest,也可以修改HttpServletResponse头和数据。
3.1 Filter 过滤结合 Servlet 的使用

想要让 Filter 可以过滤用户对 Servlet 发送的请求,必须满足如下两个条件:


  • 第一个:在 Filter 过滤器当中的 doFilter() 方法中编写:chain.doFilter(request, response) 方法:该方法的作用是:执行下一个过滤器,如果下面没有过滤器了(Filter 过滤器之间的 映射路径是相同的情况下),执行最终的Servlet(在Servlet 与 Filter 过滤器的映射路径是相同的情况下。)
  1. @Override
  2.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  3.         // 执行下一个过滤器,如果下面没有过滤器了,执行最终的Servlet
  4.         chain.doFilter(request,response);
  5.     }
复制代码

  • 第二:用户发送的请求路径是否和Servlet的请求路径一致。而 Filter过滤器的映射路径是否包含/和Servlet的请求路径一致。只有 Filter 过滤器映射路径包含/和 Servlet 的请求映射路径是一致的,Filter才会过滤该用户方法的请求信息。
  • 注意:Filter的优先级,天生的就比Servlet优先级高。:比如:/a.do 对应一个Filter,也对应一个Servlet。那么一定是先执行Filter,然后再执行Servlet。
举例:
  1. package com.RainbowSea.filter;
  2. import jakarta.servlet.Filter;
  3. import jakarta.servlet.FilterChain;
  4. import jakarta.servlet.FilterConfig;
  5. import jakarta.servlet.ServletException;
  6. import jakarta.servlet.ServletRequest;
  7. import jakarta.servlet.ServletResponse;
  8. import jakarta.servlet.annotation.WebFilter;
  9. import java.io.IOException;
  10. @WebFilter("/a.do")
  11. public class TestFilter implements Filter {
  12.     @Override
  13.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  14.         System.out.println("TestFilter 中的 doFilter() 方法 begin 开始执行了");
  15.         // 表示:执行下一个 Filter(同一个 映射的路径,如果有下一个Filter 的话),没有就执行(同一个映射的路径的 Servlet )
  16.         chain.doFilter(request,response);
  17.         System.out.println("TestFilter 中的 doFilter() 方法 end 执行结束");
  18.     }
  19. }
复制代码
  1. package com.RainbowSea.servlet;
  2. import jakarta.servlet.ServletException;
  3. import jakarta.servlet.annotation.WebServlet;
  4. import jakarta.servlet.http.HttpServlet;
  5. import jakarta.servlet.http.HttpServletRequest;
  6. import jakarta.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. @WebServlet("/a.do")
  9. public class AServlet extends HttpServlet {
  10.     @Override
  11.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
  12.             IOException {
  13.         System.out.println("AServlet 执行了");
  14.     }
  15. }
复制代码
测试效果:



案例举例:
LoginFilter 过滤器,获取到客户端发送过来的请求,进行一个过滤,判断用户的账号和密码是否正确,正确的话,LoginFilter  过滤器放行,到 LogServlet 表示登录成功。如果用户的账号和密码是错误的,则让提示用户密码错误,请重新登录。
这里为了方便演示核心,我们就将 账号和密码写死了,账号为: admin ,密码为 123
  1. package com.RainbowSea.filter;
  2. import jakarta.servlet.Filter;
  3. import jakarta.servlet.FilterChain;
  4. import jakarta.servlet.ServletException;
  5. import jakarta.servlet.ServletRequest;
  6. import jakarta.servlet.ServletResponse;
  7. import jakarta.servlet.annotation.WebFilter;
  8. import jakarta.servlet.http.HttpServletRequest;
  9. import jakarta.servlet.http.HttpServletResponse;
  10. import java.io.IOException;
  11. @WebFilter("/login")
  12. public class LoginFilter implements Filter {
  13.     @Override
  14.     public void doFilter(ServletRequest requ, ServletResponse resp, FilterChain chain) throws IOException,
  15.             ServletException {
  16.         HttpServletRequest request = (HttpServletRequest) requ;
  17.         HttpServletResponse  response= (HttpServletResponse) resp;
  18.         request.setCharacterEncoding("UTF-8");  // 设置获取到的请求信息的字符编码:
  19.         // 获取到用户的请求信息
  20.         String name = request.getParameter("user");
  21.         String password = request.getParameter("password");
  22.         // 过滤器:判断用户登录的账号和密码是否正确
  23.         if ("admin".equals(name) && "123".equals(password)) {
  24.             // 正确:放行
  25.             // 表示:执行下一个 Filter(同一个 映射的路径,如果有下一个Filter 的话),没有就执行(同一个映射的路径的 Servlet )
  26.             chain.doFilter(request,response);
  27.         } else {
  28.             // 跳转至登录失败的页面
  29.             response.sendRedirect(request.getContextPath()+"/error.jsp");
  30.         }
  31.     }
  32. }
复制代码
  1. package com.RainbowSea.servlet;
  2. import jakarta.servlet.ServletException;
  3. import jakarta.servlet.annotation.WebServlet;
  4. import jakarta.servlet.http.HttpServlet;
  5. import jakarta.servlet.http.HttpServletRequest;
  6. import jakarta.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. import java.io.PrintWriter;
  9. @WebServlet("/login")
  10. public class LoginServlet extends HttpServlet {
  11.     @Override
  12.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  13.         response.setContentType("text/html;charSet=utf-8");
  14.         PrintWriter writer = response.getWriter();
  15.         writer.println("登录成功");
  16.     }
  17. }
复制代码
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4.     <title>Title</title>
  5. </head>
  6. <body>
  7. <h3>登录失败,请重新登录</h3>
  8. </body>
  9. </html>
复制代码


Filter 过滤器的生命周期

当Web容器启动时,会根据web.xml中声明的filter顺序依次实例化这些filter。然后在Web应用程序加载时调用init()方法,随机客户端有请求时调用doFilter()方法,并且根据实际情况的不同,doFilter()方法可能被调用多次。最后Web应用程序卸载时调用destroy()方法。
Filter 过滤器与 Servlet 的区别:

  • servlet对象默认情况下,在服务器启动的时候是不会新建对象的。
  • Filter对象默认情况下,在服务器启动的时候会新建对象。
  • Servlet是单例的。Filter也是单例的。(单实例,但是它们都是假单例,因为真单例的构造器是 private 的,而这两个类都不是私有的构造器)
  • Filter 和Servlet对象生命周期一致。
  • 唯一的区别:Filter默认情况下,在服务器启动阶段就实例化。Servlet不会。
  • Filter的优先级,天生的就比Servlet优先级高。比如:/a.do 对应一个Filter,也对应一个Servlet。那么一定是先执行Filter,然后再执行Servlet。
4. Filter 过滤器的拦截路径:

关于Filter的配置路径:不同的 Filter 映射路径,所拦截用户请求的也是不一样的。
关于 Filter 过滤器路径的配置:大致可以分别如下四种:

  • 精确匹配路径:/a.do、/b.do、/dept/save。这些配置方式都是精确匹配。
  • 目录匹配:/admin/*  


  • 匹配所有路径: /*
  • 前后缀名路径匹配:后缀:*.do 后缀匹配。不要以 / 开始,前缀:/dept/*  前缀匹配。
4.1 精确匹配路径

只有完美匹配,一个符号,一个字符,不能错误的路径。Filter 只会过滤用户访问该:/target/dep路径的信息才会拦截判断是否放行。其他用户访问的路径一概不会进行 Filter  过滤器过滤
  1. <filter-mapping>
  2.     <filter-name>Filter</filter-name>
  3.     <url-pattern>/target/dep</url-pattern>  
  4. </filter-mapping>
复制代码
4.2 目录匹配

Filter 会过滤用户访问该:/admin/* admin子路径包含 admin路径的信息:比如:/admin/test/admin/test/test2才会拦截判断是否放行。其他用户访问的路径一概不会进行 Filter  过滤器过滤。
  1. <filter-mapping>
  2.     <filter-name>Filter</filter-name>
  3.     <url-pattern>/admin/*</url-pattern>
  4. </filter-mapping>
复制代码
4.3 前后缀名路径匹配

后缀路径匹配:以上配置的路径,表示请求地址必须以.do 结尾才会被 Filter 过滤器拦截判断是否放行。
注意的是:不要以 / 开始 ,不然就失效了。
  1. <filter-mapping>
  2.     <filter-name>Filter</filter-name>
  3.     <url-pattern>*.do</url-pattern>
  4. </filter-mapping>
复制代码
前缀路径匹配:以上配置的路径,表示请求地址必须以/admin/ 开头才会被 Filter 过滤器拦截判断是否放行
  1. <filter-mapping>
  2.     <filter-name>Filter</filter-name>
  3.     <url-pattern>/admin/*</url-pattern>
  4. </filter-mapping>
复制代码
4.4 所有路径匹配

/* 表示对应任何请求地址,Filter 过滤器都会进行一个拦截判断是否放行,那么这个路径的资源不存在也会,进行一个拦截判断是否放行。这种方式虽然简单,但是,这个代价比较到,效率低,对于特殊的路径请求要放行的你可能需要编写大量的逻辑判断进行一个拦截放行。不建议使用。
  1. <filter-mapping>
  2.     <filter-name>Filter</filter-name>
  3.     <url-pattern>/*</url-pattern>
  4. </filter-mapping>
复制代码
5. 设置 Filter 执行顺序

一个 Servelt 是可以设置多个 Filter 过滤器的,当我们设置了多个 Filter 过滤器,其中 Filter 过滤器的执行顺序该如何设置呢?
从上面文章的内容,我们知道了 Filter 的映射路径设置有两种方式:

  • 注解:@WebFilter()
  • 配置 web.xml 文件的方式。这种方式 推荐使用
两种设置 Filter的方式不同,对于设置的执行顺序的方式也是不一样的。
对于 Filter 执行顺序的设置,虽然有两种方式,但是推荐使用 web.xml 配置文件的方式,因为使用 注解@WebFilter() 的方式的话,我们需要更加定义的类名的字母顺序的方式来,设置Filter的执行顺序,这样会改变一个类名的见名之意。而如果是使用 web.xml 配置文件的方式,直接更加 Filtet 编写的配置是先后顺序就可以了。
过滤器的调用顺序,遵循栈数据结构。
第一种:注解的方式:设置Filter过滤器的执行顺序:
注解的方式:
执行顺序是:比较 Filter 这个类名。就是你定义的这个类名 implements (实现) Filter 的类名


  • 比如:FilterA和FilterB,则先执行FilterA
  • 比如:Filter1和Filter2,则先执行Filter1
举例验证:




通过:配置 web.xml 文件的方式,如何设置 Filter 的执行顺序:
在 web.xml 中是:依靠 标签的配置位置,越靠上优先级越高,就越先执行其中的 Filter的 doFilter() 方法。
举例证实:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
  5.          version="5.0">
  6.     <filter>
  7.         <filter-name>FilterB</filter-name>
  8.         <filter-class>com.RainbowSea.filter.FilterB</filter-class>
  9.     </filter>
  10.     <filter-mapping>
  11.         <filter-name>FilterB</filter-name>
  12.         <url-pattern>/A</url-pattern>
  13.     </filter-mapping>
  14.     <filter>
  15.         
  16.         <filter-name>FilterA</filter-name>
  17.         
  18.         <filter-class>com.RainbowSea.filter.FilterA</filter-class>
  19.     </filter>
  20.     <filter-mapping>
  21.         <filter-name>FilterA</filter-name>
  22.         
  23.         <url-pattern>/A</url-pattern>
  24.     </filter-mapping>
  25. </web-app>
复制代码
  1. package com.RainbowSea.servlet;
  2. import jakarta.servlet.ServletException;
  3. import jakarta.servlet.annotation.WebServlet;
  4. import jakarta.servlet.http.HttpServlet;
  5. import jakarta.servlet.http.HttpServletRequest;
  6. import jakarta.servlet.http.HttpServletResponse;
  7. import java.io.IOException;
  8. @WebServlet("/A")
  9. public class AServlet extends HttpServlet {
  10.     @Override
  11.     protected void doGet(HttpServletRequest request, HttpServletResponse response)
  12.             throws ServletException,
  13.             IOException {
  14.         System.out.println("AServlet doGet()  执行了");
  15.     }
  16. }
复制代码
  1. package com.RainbowSea.filter;
  2. import jakarta.servlet.Filter;
  3. import jakarta.servlet.FilterChain;
  4. import jakarta.servlet.ServletException;
  5. import jakarta.servlet.ServletRequest;
  6. import jakarta.servlet.ServletResponse;
  7. import java.io.IOException;
  8. public class FilterB implements Filter {
  9.     @Override
  10.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  11.             throws IOException, ServletException {
  12.         System.out.println("FilterB doFilter() 执行了");
  13.         // 表示执行后面的(映射路径相同的Filter 过滤器),如果后面没有的话执行(映射路径相同的 Servlet)
  14.         chain.doFilter(request,response);
  15.     }
  16. }
复制代码
  1. package com.RainbowSea.filter;
  2. import jakarta.servlet.Filter;
  3. import jakarta.servlet.FilterChain;
  4. import jakarta.servlet.ServletException;
  5. import jakarta.servlet.ServletRequest;
  6. import jakarta.servlet.ServletResponse;
  7. import java.io.IOException;
  8. public class FilterA implements Filter {
  9.     @Override
  10.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  11.             throws IOException, ServletException {
  12.         System.out.println("FilterA  doFilter() 执行了");
  13.         // 表示执行后面的(映射路径相同的Filter 过滤器),如果后面没有的话执行(映射路径相同的 Servlet)
  14.         chain.doFilter(request,response);
  15.     }
  16. }
复制代码

6. Filter 过滤器中的责任链设计模式思想

23种设计模式 : 责任链设计模式
过滤器最大的优点:
在程序编译阶段不会确定调用顺序。因为Filter的调用顺序是配置到web.xml文件中的,只要修改web.xml配置文件中filter-mapping的顺序就可以调整Filter的执行顺序。显然Filter的执行顺序是在程序运行阶段动态组合的。那么这种设计模式被称为责任链设计模式。
责任链设计模式最大的核心思想:在程序运行阶段,动态的组合程序的调用顺序。在上面对于 Filter的使用当中,我们已经体验到了,Filter 的动态调用其中的 doFilter() 方法,通过修改其中的 web.xml 对 Filter 的配置顺序。
下面我们演示一下不是 :责任链设计模式的方式:
如下这种方式:是我们写死了的,想要改变其中的执行顺序,就必须通过修改其中的源码当中的,代码的执行顺序,无法通过通过配置文件的方式,修改调用的顺序。
  1. package com.RainbowSea.filter;
  2. public class Test {
  3.     public static void main(String[] args) {
  4.         m1();
  5.     }
  6.     private static void m1() {
  7.         System.out.println("m1() begin ");
  8.         m2();
  9.         System.out.println("m1() end ");
  10.     }
  11.     private static void m2() {
  12.         System.out.println("m2() begin ");
  13.         m3();
  14.         System.out.println("m2() end ");
  15.     }
  16.     private static void m3() {
  17.         System.out.println("m3() begin ");
  18.         System.out.println("m3() end ");
  19.     }
  20. }
复制代码

7. 运用 Filter 过滤器的方式优化  oa 项目的一个登录验证:


关于 oa 项目的,大家可以移步至
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

泉缘泉

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表