多个Filter的执行顺序 | 职责链模式应用_多个filter执行顺序-程序员宅基地

技术标签: JAVA  java  tomcat  servlet  

前言

  Filter(过滤器) 是 Java Servlet 规范中定义的一种组件,用于在请求到达 Servlet 之前或响应返回给客户端之前对请求和响应进行处理。Filter 的主要作用是拦截、修改或处理传入的请求和传出的响应。

  tomcat作为web容器,提供了对 Filter 的支持。Tomcat 开启了Filter 的生命周期,当请求到达 Tomcat 时,Tomcat 将根据配置的 Filter 映射将请求传递给相应的 Filter。

  Filter 可以设置多个,并且按照一定顺序依次执行,这是因为使用了设计模式中的职责链模式。



一、多个Filter的执行顺序

1. 配置web.xml方式注册Filter

  自定义过滤器:

public class FilterOne implements Filter{
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
        System.out.println("过滤器1执行——————————————————————————————————————");
        chain.doFilter(request,response);
    }
}
public class FilterTwo implements Filter{
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
        System.out.println("过滤器2执行——————————————————————————————————————");
        chain.doFilter(request,response);
    }
}
public class FilterThree implements Filter{
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
        System.out.println("过滤器3执行——————————————————————————————————————");
        chain.doFilter(request,response);
    }
}

  配置 web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
         
  <!--注册SpringMVC的前端控制器——DispatcherServlet-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--关联配置文件-->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--启动级别1-->
    <load-on-startup>1</load-on-startup>
  </servlet>

  <!--/ 匹配所有请求,不包括jsp-->
  <!--/* 匹配所有请求,包括jsp-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!--配置过滤器FilterOne、FilterTwo、FilterThree-->
  <filter>
    <filter-name>FilterThree</filter-name>
    <filter-class>com.config.FilterThree</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterThree</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <filter>
    <filter-name>FilterOne</filter-name>
    <filter-class>com.config.FilterOne</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterOne</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <filter>
    <filter-name>FilterTwo</filter-name>
    <filter-class>com.config.FilterTwo</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>FilterTwo</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

结论:

  进入调试模式,可以看到过滤器统一放在一个容器中,顺序就是web.xml中从上到下的设置顺序。
在这里插入图片描述

  最后出来的打印执行顺序如下:按照解析web.xml的顺序添加的过滤器,并按照添加顺序执行的。
请添加图片描述



2. 注解方式注册Filter

  自定义过滤器:

@WebFilter(filterName = "FilterOne", urlPatterns = {
    "/*"})
public class FilterOne implements Filter{
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
        System.out.println("过滤器1执行——————————————————————————————————————");
        chain.doFilter(request,response);
    }
}
@WebFilter(filterName = "FilterThree", urlPatterns = {
    "/*"})
public class FilterThree implements Filter{
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
        System.out.println("过滤器3执行——————————————————————————————————————");
        chain.doFilter(request,response);
    }
}
@WebFilter(filterName = "FilterTwo", urlPatterns = {
    "/*"})
public class FilterTwo implements Filter {
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
        System.out.println("过滤器2执行——————————————————————————————————————");
        chain.doFilter(request,response);
    }
}

结论:

  最后出来的打印执行顺序如下:
在这里插入图片描述


   根据类名的字母顺序排序,也就是说按字母顺序添加的过滤器,并且也按添加顺序执行的。
在这里插入图片描述



二、职责链模式的应用

1. 回顾职责链模式

  先来回顾职责链模式的特点:职责链模式——向上级申请加薪
  职责链模式特点如下:

  • 分离发送者和接收者:将发送者和接收者解耦,发送者只需要将请求发送给职责链的起始节点,而不需要知道具体的接收者。接收者也不需要知道请求的发送者是谁。

  • 多个处理节点处理请求:请求会在职责链上的多个处理节点中依次传递,每个节点都有机会处理请求。这样可以将复杂的处理逻辑分解成多个独立的节点。

  • 请求的处理可以终止:每个处理节点都可以决定是否继续传递请求给下一个节点或终止处理。这样可以灵活地控制请求的处理流程。

在这里插入图片描述

2. Filter职责链模式的应用

  所有过滤器都实现了doFilter方法,但是没有设置下级链的方法。
在这里插入图片描述
  Tomcat包中的ApplicationFilterFactory类中有个createFilterChain()方法,它的主要作用是将一组 Filters 以特定的顺序组合成一个 FilterChain,自动设置好了每一链的下级链。

  FilterChain 将被用于处理传入的请求,按照预定的顺序调用相应的 Filters 和最终的 Servlet(请求的方法)。
  例如:
在这里插入图片描述


  createFilterChain()方法大致的工作内容:

  1. 根据web.xml配置的 Filter 映射和顺序创建一个 FilterChain 对象。
  2. 将 FilterChain 初始化为包含所有配置的Filters,并按照预定的顺序进行排序。
  3. 返回创建的FilterChain 对象。


总结

  Filter 使用职责链模式(Chain of Responsibility Pattern)的优势:

  • 分离责任:将处理逻辑分散到多个 Filter 中,每个 Filter 只负责特定的处理任务。这样可以将复杂的处理逻辑分解为多个独立的模块,每个模块只关注自己的责任,实现了职责的分离。

  • 可扩展性:支持添加、移除和调整处理节点。可以根据需要增加新的 Filter,也可以移除或替换现有的 Filter,而不需要修改已有的代码。这使得系统具有良好的扩展性,可以灵活地应对变化的需求。

  • 可重用性:每个 Filter 负责独立的处理任务,可以被多个不同的请求或系统复用。这样可以避免重复编写相同的处理逻辑,提高代码的可重用性和可维护性。

  • 灵活性:允许根据实际需求动态调整处理流程。可以根据请求的类型、状态或其他条件来动态选择、排列和调整 Filter 的顺序,从而灵活地定制处理流程,以满足不同的业务需求。

  通过使用职责链模式,Filter 可以形成一个灵活、可扩展和可定制的处理链,每个 Filter 只负责特定的处理任务,处理逻辑分散到不同的节点中,实现了解耦合和职责的分离。这样可以提高代码的可维护性、可重用性和灵活性,同时使系统能够适应变化的需求。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CharmaineXia/article/details/130803350

智能推荐

Scrapy集成Selenium ChromeDriver_scrapy driver-程序员宅基地

文章浏览阅读2.7k次。官网chromedriverchromedriver-downloadsRunning Selenium Headless with Chrome安装chrome浏览器1、windows可通过 帮助->关于Google Chrome查看已安装的Chrome版本2、linuxTODO下载chromdriver下载链接:https://sites.google.com/a/chromium.org/chromedriver/downloads1、选择对应的版本2、选择对应的操作系_scrapy driver

00_Ubuntu系统入门_ubuntu入门-程序员宅基地

文章浏览阅读3k次,点赞11次,收藏88次。Ubuntu系统入门,shell,Makefile。_ubuntu入门

【bzoj1798】[Ahoi2009]Seq 维护序列seq 线段树-程序员宅基地

文章浏览阅读252次。原题题解:线段树区间乘法,lazy标记的更新对于我这种萌新来说是个难点qwq。先理清楚想好了再写。先乘后除,一步一步慢慢来。//bzoj1798 [Ahoi2009]维护序列#include&lt;iostream&gt;#include&lt;cstdio&gt;#include&lt;cstring&gt;#define lson l,m,pos&lt;&lt;1#define rs...

微信小程序使用weui样式框架-程序员宅基地

文章浏览阅读2.8k次。WeUI 是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。包含button、cell、dialog、 progress、 toast、article、actionsheet、icon等各式元素。以下内容是纯UI库,如果想使用逻辑封装版本,请看小程序组件库 - WeUIWEUI的组件库这篇文章只介绍样式如何引入↓↓↓github下载:weui-wxss将dist文件导入到微信开发者工具3.看到这个界面就说明._weui样式

mysql中有检查约束吗_mysql中的检查约束有什么用-程序员宅基地

文章浏览阅读540次。mysql中的检查约束的作用:用来指定某列的可取值的范围。检查约束可以通过CREATE TABLE或ALTER TABLE语句来实现,根据用户实际的完整性要求来定义。在MySQL中,提供了CHECK检查约束用来指定某列的可取值的范围,它通过限制输入到列中的值来强制域的完整性。但是目前的MySQL版本只是对CHECK约束进行了分析处理,但会被直接忽略,并不会报错。MySQL 检查约束(CHECK)可..._在目前的mysol版本中,check完整性约束能够解析,但会被忽略

开源项目-CSV导入导出工具类_opencsv官网-程序员宅基地

文章浏览阅读2k次,点赞29次,收藏30次。github上提升效率的轮子推荐(二)_opencsv官网

随便推点

MATLAB中cvx工具箱的使用介绍-程序员宅基地

文章浏览阅读1.4k次,点赞10次,收藏26次。cvx工具箱_cvx工具箱

配置oracle用户的环境变量,window中oracle环境变量设置方法分享-程序员宅基地

文章浏览阅读686次。window server中Oracle的环境变量设置1、右击“我的电脑”->选择“属性”->选择“高级”->单击“环境变量”2、选择“Path”这一行,单击“编辑”,在“Path”的变量值文本框的最后面先加入一个分号“:”,然后再分号后面加入sqlplus文件的目录路径,如“C:\Program Files\oracle\product\10.2.0\db_1\BIN”,然后点..._windows系统oracle监听需要修改哪些环境变量

Oracle11g安装配置详细教程_oracle11g安装配置详细教程 csdn-程序员宅基地

文章浏览阅读701次,点赞22次,收藏9次。Oracle 11g的安装和配置是一个详尽的过程,涉及多个步骤。以下是基于Oracle 11g R2(第二个发布版本)在Windows环境下的安装和基本配置的概述。请注意,Oracle 11g在不同的操作系统上的安装步骤可能会有所不同,此处以Windows为例进行说明。_oracle11g安装配置详细教程 csdn

不能将参数1从 "_TCHAR*" 转换为"const char *"_无法将参数1 从tchar转换为ptchar-程序员宅基地

文章浏览阅读3.2k次,点赞3次,收藏3次。VS解决方案:项目——属性——配置——属性——常规——字符集:“使用Unicode字符集” 改为 “使用多字节字符集”。_无法将参数1 从tchar转换为ptchar

在matlab中可以计算式子的最大值吗,matlab求最大值-程序员宅基地

文章浏览阅读785次。matlab遗传算法求最大值问题例题完整代码_IT认证_资格考试/认证_教育专区。matlab遗传算法求最大值问题例题完整代码 本文件的目的是减少您打字的烦恼 %主程序:用......11MATLAB求函数极值_数学_自然科学_专业资料。教学过程与内容: 求函数极小值命令格式:[x,minf]=fminbnd(‘f’,a,b) 求函数极大值命令格式:[x,maxf]=fmin......线性规划求..._给定两个参数的范围,怎么用matlab求其式子相乘最大值

第2-5节项目6(4)-回文、素数_c语言键盘接收两个正整数,输出它们之间的最大6个回文素数。要求每行输出两个数。-程序员宅基地

文章浏览阅读140次。问题及代码:/*Copyright(c)2018,CSDN学院行者-All rights reserved.文件名称:main.c作者:乔帅完成日期:2018年2月1日版本号:v1.0问题描述:回文、素数输入描述:无输入程序输出:输出1000以内的素数、回文数、回文素数、可逆素数*/#include#includeint isPrimer(int);int _c语言键盘接收两个正整数,输出它们之间的最大6个回文素数。要求每行输出两个数。