FilterChain(过滤器链)详解

news2025/1/23 22:36:18

在一个 Web 应用程序中可以注册多个 Filter 程序,每个 Filter 程序都可以针对某一个 URL 进行拦截。如果多个 Filter 程序都对同一个 URL 进行拦截,那么这些 Filter 就会组成一个Filter 链(也称过滤器链)。

Filter 链用 FilterChain 对象表示,FilterChain 对象中有一个 doFilter() 方法,该方法的作用是让 Filter 链上的当前过滤器放行,使请求进入下一个 Filter。

Filter 链的拦截过程如图 1 所示。


图 1 Filter链

在图 1 中,当浏览器访问 Web 服务器中的资源时,需要经过两个过滤器 Filter1 和 Filter2。首先 Filter1 会对这个请求进行拦截,在 Filter1 中处理完请求后,通过调用 Filter1 的 doFilter() 方法将请求传递给 Filter2,Filter2 处理用户请求后同样调用 doFilter() 方法,最终将请求发送给目标资源。当 Web 服务器对这个请求做出响应时,也会被过滤器拦截,但这个拦截顺序与之前相反,最终将响应结果发送给客户端浏览器。

为了便于读者理解 Filter 链的拦截过程以及掌握 Filter 链的使用,下面通过案例演示如何使用 Filter 链拦截 MyServlet 的同一个请求。

1)创建过滤器

在 filterDemo01 项目的 com.mengma.filter 包中新建两个过滤器 MyFilter01 和 MyFilter02,如 MyFilter01 和 MyFilter02 所示。

① MyFilter01

  1. package com.mengma.filter;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.Filter;
  5. import javax.servlet.FilterChain;
  6. import javax.servlet.FilterConfig;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. public class MyFilter01 implements Filter {
  11. public void init(FilterConfig fConfig) throws ServletException {
  12. // 过滤器对象在初始化时调用,可以配置一些初始化参数
  13. }
  14. public void doFilter(ServletRequest request, ServletResponse response,
  15. FilterChain chain) throws IOException, ServletException {
  16. // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,则该方法会被调用
  17. PrintWriter out = response.getWriter();
  18. out.write("MyFilter01<br/>");
  19. chain.doFilter(request, response);
  20. }
  21. public void destroy() {
  22. // 过滤器对象在销毁时自动调用,释放资源
  23. }
  24. }

② MyFilter02

  1. package com.mengma.filter;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import javax.servlet.Filter;
  5. import javax.servlet.FilterChain;
  6. import javax.servlet.FilterConfig;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. public class MyFilter02 implements Filter {
  11. public void init(FilterConfig fConfig) throws ServletException {
  12. // 过滤器对象在初始化时调用,可以配置一些初始化参数
  13. }
  14. public void doFilter(ServletRequest request, ServletResponse response,
  15. FilterChain chain) throws IOException, ServletException {
  16. // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,则该方法会被调用
  17. PrintWriter out = response.getWriter();
  18. out.write("MyFilter02 Before<br/>");
  19. chain.doFilter(request, response);
  20. out.write("<br/>MyFilter02 After<br/>");
  21. }
  22. public void destroy() {
  23. // 过滤器对象在销毁时自动调用,释放资源
  24. }
  25. }

2)修改 web.xml

为了防止其他过滤器影响此次 Filter 链的演示效果,需要先将 web.xml 文件中的其他过滤器的配置信息注释掉,然后将 MyFilter01 和 MyFilter02 过滤器的映射信息配置在 MyServlet 配置信息前面,具体如下所示。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  5. version="3.0">
  6. <filter>
  7. <filter-name>MyFilter01</filter-name>
  8. <filter-class>com.mengma.filter.MyFilter01</filter-class>
  9. </filter>
  10. <filter-mapping>
  11. <filter-name>MyFilter01</filter-name>
  12. <url-pattern>/MyServlet</url-pattern>
  13. </filter-mapping>
  14. <filter>
  15. <filter-name>MyFilter02</filter-name>
  16. <filter-class>com.mengma.filter.MyFilter02</filter-class>
  17. </filter>
  18. <filter-mapping>
  19. <filter-name>MyFilter02</filter-name>
  20. <url-pattern>/MyServlet</url-pattern>
  21. </filter-mapping>
  22. <servlet>
  23. <servlet-name>MyServlet</servlet-name>
  24. <servlet-class>com.mengma.filter.MyServlet</servlet-class>
  25. </servlet>
  26. <servlet-mapping>
  27. <servlet-name>MyServlet</servlet-name>
  28. <url-pattern>/MyServlet</url-pattern>
  29. </servlet-mapping>
  30. </web-app>

3)运行项目并查看结果

启动 Tomcat 服务器,在浏览器的地址栏中输入 http://localhost:8080/filterDemo01/MyServlet,此时,浏览器窗口中的显示结果如图 2 所示。


图 2 运行结果

从图 2 中可以看出,MyServlet 首先被 MyFilter01 拦截了,显示出 MyFilter01 中的内容,然后被 MyFilter02 拦截,直到 MyServlet 被 MyFilter02 放行后,浏览器才显示出 MyServlet 中的输出内容。

需要注意的是,Filter 链中各个 Filter 的拦截顺序与它们在 web.xml 文件中 <filter-mapping> 元素的映射顺序一致,由于 MyFilter01 的 <filter-mapping> 元素位于 MyFilter02 的 <filter-mapping> 元素前面,因此,用户的访问请求首先会被 MyFilter01 拦截,然后再被 MyFilter02 拦截。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/408130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue获取文件流(视频流、音频流、图片流)数据并将其回显展示

前言 这几天深受数据回显的折磨&#xff0c;级联选择器的回显还没想出怎么弄&#xff0c;又碰到了文件流的回显&#xff0c;主要第一次接触&#xff0c;看着一堆乱码&#xff0c;连是什么问题都不懂&#xff0c;后面通过查阅一天的资料&#xff0c;总结了一下方法&#xff0c;…

Axure教程-新手入门基础(小白强烈推荐!!!)

Axure教程-新手入门基础(小白推荐) 1.Axure软件介绍 Axure RP是一款专业的快速原型设计工具。Axure&#xff08;发音&#xff1a;Ack-sure&#xff09;&#xff0c;代表美国Axure公司&#xff1b;RP则是Rapid Prototyping&#xff08;快速原型&#xff09;的缩写。 Axure RP的…

Code For Better 谷歌开发者之声——使用谷歌浏览器 Chrome 更好地调试

&#x1f482; 个人网站:【 海拥】【小霸王游戏机】&#x1f91f; 风趣幽默的前端学习课程&#xff1a;&#x1f449;28个案例趣学前端&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】&#x1f4ac; 免费且实用的计算机相关知识题库&…

layui最新版本更新已全面拥抱Vue3,layui - vue是一套Vue 3.0的桌面端组件库,提供100%的layui的体验;

layui - vue目前的版本是1.4.9&#xff0c;目前常用的大部分组件已全部覆盖&#xff0c;最惊喜的地方在动画和过度组件做的比较好&#xff0c;应该是目前Vue组件库里面做的比较好的&#xff0c;Vue的动画相比于React和Angular一直比较弱,layui - vue目前做的不错&#xff0c;目…

前端中的BFC是什么?

BFC的概念 BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域&#xff0c;只有Block-level box参与&#xff0c; 它规定了内部的Block-level Box如何布局&#xff0c;并且与这个区域外部毫不相干。 MDN给出的解释是&#xff1a;BFC是…

【docker基础操作命令】(一)启动命令和镜像命令

文章目录docker启动命令1. 启动docker2. 关闭docker3. 重启docker4. 查看docker运行状态5. 设置docker开机自启动6. 查看docker信息7. 查看docker的帮助文档docker镜像命令1. 显示当前docker下的所有镜像2. 从远程仓库查看指定名称的镜像3. 下载镜像到本地4. 查看镜像/容器/数据…

分布式ELK日志监控系统环境搭建

文章目录1.1为什么需要监控项目日志1.2ELK日志监控系统介绍1.3ELK的工作流程1.4ELK环境搭建1.4.1Elasticsearch的安装1.4.2Kibana的安装1.4.3Logstash的安装1.4.4数据源配置1.4.5日志监测测试1.1为什么需要监控项目日志 项目日志是记录项目运行过程中产生的事件和信息的重要工…

web前端开发和后端开发哪个难度大?

前言 因为涉及到的具体的应用的领域不同&#xff0c;所以说不能简单地说哪一个难&#xff0c;对于前端而言你会感觉到入门会非常的简单&#xff0c;这也是会给许多人一种错觉&#xff0c;前端很简单&#xff0c;但是只能说是在入门理解上是有利于新手的&#xff0c;前端在主要…

Python tkinter(GUI编程)模块最完整教程(上)

提示&#xff1a;下滑文章左侧可以查看目录&#xff01; 1 走进tkinter世界 1.1 认识tkinter tkinter是一个GUI开发模块&#xff0c;是Tcl/Tk语言在Python上的接口&#xff0c;可以在大部分操作系统上运行。tkinter非常的简单而且好用。tkinter模块是自带的Python模块&#…

vue3.2 基础及常用方法

Vue3.2(21年8月10日)相比于Vue3新增了语法糖,减少了代码冗余 Vue3相比于Vue2,在虚拟DOM,编译, 数据代理,打包构建封面进行了优化 Vue3使用组合式API, 适合大型项目, 去除了this vue2的 beforeCreate 和 created 被新增的setup生命周期替代 vue3 使用插件: volar 配置用户代…

js中常遇到 切割截取字符串的几种方法

切割截取字符串的几种方法 1、 split() 方法用于把一个 字符串 分割成 字符串数组 &#xff1b; stringObject.split(str,length)var str "123,456,789"; console.log(str.split()); // ["1", "2", "3", ",", "4&qu…

【PC端聊天功能模板】vue-elementul简单实现电脑端客服聊天功能,pc端聊天系统静态页面布局,配套websocket方案和心跳重连机制【详细注释,拿来即用】

前言 这里是给大家写了一个简单的模板来使用&#xff0c;可以直接复制了调调就能用。因为这个聊天也是很容易出现的功能&#xff0c;所以我写一个模板静态页面放在这&#xff0c;以后需要这个功能的时候可以不用布局了&#xff0c;直接复制改改。 我的代码里面有详细的注释&…

小马带你认识前端开发神器WebStorm(WebStorm及Git的相关配置与使用)

先说一下个人感觉吧&#xff0c;小马之前也是一直在用 Visual Studio Code 来进行开发&#xff0c;但随着开发需求增加&#xff0c;VS 所需要的插件越来越多&#xff08;用过 vs code 的同学都知道&#xff0c;它虽可以进行各种开发语言的编写&#xff0c;但是需要相应的插件支…

ECharts设置x轴刻度间隔的两种方法

ECharts设置x轴刻度文字间隔的两种方法 背景 最近在写一个echarts数据看板&#xff0c;要在一个页面中展示多张图表&#xff0c;所以留给每张图表的尺寸就很小。这也就使得图表x轴的刻度文字全部挤到一起了&#xff0c;废话不多说&#xff0c;直接上图看效果。 右边的图标就…

11.定时任务定时线程池详解

3.1 新增定时任务池 11.定时任务&定时线程池详解 ​ 当我们不用任务框架时&#xff0c;我们想自己写一个定时任务时&#xff0c;我们能想起那个工具类呢&#xff1f;Timer &#xff1f;还有吗&#xff1f;不知道了&#xff0c;下面我们要讲下ScheduledThreadPoolExecutor…

Vue图片路径问题(动态引入:绝对路径、相对路径),require动态路径问题

Vue图片路径问题&#xff08;动/静态引入&#xff1a;绝对路径、相对路径&#xff09; DEMO实例&#xff08;可快速解决问题&#xff09;: 注意&#xff1a;绝对路径方式导入的图片需要存储在 publiic 文件夹下 静态导入相对路径&#xff1a; <img src"../../asset…

Mybatis+Servlet+Mysql 整合的一个小项目:对初学者非常友好,有助于初学者很快的上手Java Web

文章目录前言为何要写&#xff1f;目录结构1 依赖配置1.1 创建一个web项目1.2 依赖需求分析1.3 pom.xml2 配置Mybatis2.1 mybatis-config.xml2.2 UserMapper.xml2.3 UserMapper.interface3 配置Tomcat4 Servlet类4.1 loginServlet014.2 registerRequest015 静态页面代码5.1 Htm…

Vue开发实例(13)之axios和mockjs的安装与使用

作者简介 作者名&#xff1a;编程界明世隐 简介&#xff1a;CSDN博客专家&#xff0c;从事软件开发多年&#xff0c;精通Java、JavaScript&#xff0c;博主也是从零开始一步步把学习成长、深知学习和积累的重要性&#xff0c;喜欢跟广大ADC一起打野升级&#xff0c;欢迎您关注&…

Vue3中 内置组件 Teleport 详解

1. 基本概念 1.1 简单理解 不管是 Vue2 还是 Vue3 中都有内置组件的存在&#xff0c;如 component 内置组件、transition 内置组件等等。内置组件就是官方给我们封装的全局组件&#xff0c;我们直接拿来用就可以了。 在 Vue3 中新增了 Teleport 内置组件&#xff0c;先来看下…

【JavaScript-数组全家福】

目录 前言 数组 1.创建 new Array数组 2.检测是否为数组 1.使用instanceof检测是否为数组 2.使用Array.isArray()来检测 3.添加删除数组方法 4.筛选数组 5.数组排序 6.数组索引方法 7.数组去重 8.数组转字符串 写在最后 前言 博主是&#x1f466;一个帅气的boy&#…