当前位置: 首页 > news >正文

【Java】什么是过滤器链(FilterChain )?哪些场景可以使用过滤器链?

文章目录

  • 前言
  • 1、创建过滤器
  • 2、修改 web.xml
  • 3、运行项目并查看结果

前言

在一个 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

package com.mengma.filter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilter01 implements Filter {
public void init(FilterConfig fConfig) throws ServletException {
// 过滤器对象在初始化时调用,可以配置一些初始化参数
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,则该方法会被调用
PrintWriter out = response.getWriter();
out.write("MyFilter01<br/>");
chain.doFilter(request, response);
}
public void destroy() {
// 过滤器对象在销毁时自动调用,释放资源
}
}

② MyFilter02

package com.mengma.filter;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilter02 implements Filter {
public void init(FilterConfig fConfig) throws ServletException {
// 过滤器对象在初始化时调用,可以配置一些初始化参数
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,则该方法会被调用
PrintWriter out = response.getWriter();
out.write("MyFilter02 Before<br/>");
chain.doFilter(request, response);
out.write("<br/>MyFilter02 After<br/>");
}
public void destroy() {
// 过滤器对象在销毁时自动调用,释放资源
}
}

2、修改 web.xml

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

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<filter>
<filter-name>MyFilter01</filter-name>
<filter-class>com.mengma.filter.MyFilter01</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<filter>
<filter-name>MyFilter02</filter-name>
<filter-class>com.mengma.filter.MyFilter02</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter02</filter-name>
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.mengma.filter.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
</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 拦截。

相关文章:

【Java】什么是过滤器链(FilterChain )?哪些场景可以使用过滤器链?

文章目录 前言1、创建过滤器2、修改 web.xml3、运行项目并查看结果 前言 在一个 Web 应用程序中可以注册多个 Filter 程序&#xff0c;每个 Filter 程序都可以针对某一个 URL 进行拦截。如果多个 Filter 程序都对同一个 URL 进行拦截&#xff0c;那么这些 Filter 就会组成一个…...

Vue-video-player下载失败(npm i 报错)

Vue-video-player下载失败 最近在做项目时涉及到视频的播放组件&#xff0c;看了一下选择了Vue-video-player这个工具&#xff0c;实际在操作中是遇到许多问题的。 Q1:不支持谷歌 对于 “vue-video-player” 使用时出现 Adobe Flash 不再支持的提示&#xff0c;这是因为 Ado…...

数据在内存中的存储(1)

目录 1、整数在内存中的存储 原码、反码、补码&#xff1a; 2、大小端&#xff1a; 前提须知&#xff1a; 大小端存储方式&#xff1a; 字节的顺序&#xff1a; 概念&#xff1a; 判断机器是大端还是小端&#xff1a; 代码展示&#xff1a; 代码优化1.0&#xff1a; …...

LINUX常用命令练习

显示LINUX系统当前的日期和时间。 date以 yyyy/mm/dd的格式显示系统当前的日期 date %Y/%m/%d以 yyyy-mm-dd的格式显示系统当前的日期 date %Y-%m-%d查看在线用户信息 who显示当前月份的日历 cal显示2023年整年的日历 cal 2023显示2023年9月的日历 cal 9 2023查看LINUX系统的Sh…...

2022年全国研究生数学建模竞赛华为杯C题汽车制造涂装-总装缓存调序区调度优化问题求解全过程文档及程序

2022年全国研究生数学建模竞赛华为杯 C题 汽车制造涂装-总装缓存调序区调度优化问题 原题再现&#xff1a; 背景介绍   汽车制造厂主要由焊装车间、涂装车间、总装车间构成&#xff0c;每个车间有不同的生产偏好&#xff0c;如&#xff1a;焊装车间由于车身夹具的限制偏向最…...

文本直接生成3D游戏场景、功能,用ChatGPT方式开发游戏!

3D游戏开发平台Hiber3D通过谷歌的PaLM大语言模型&#xff0c;结合自身500多个模板库&#xff0c;以及数百万个成品3D场景进行微调&#xff0c;推出了一个全新游戏开发平台。 该平台在生成式AI加持下&#xff0c;用户可以像使用ChatGPT那样&#xff0c;通过文本问答方式快速创建…...

2023年会展行业研究报告

第一章 行业概况 1.1 定义 会展行业是一个多元化和复杂的领域&#xff0c;涵盖了许多不同的活动和功能。一般来说&#xff0c;会展业是指在一定的区域空间内&#xff0c;许多人聚集在一起形成的定期或者不定期&#xff0c;制度或者非制度&#xff0c;传递和交流信息的群众性的…...

【Redis】如何保证Redis缓存与数据库的一致性?

文章目录 1、四种同步策略2、更新缓存还是删除缓存2.1 更新缓存2.2 删除缓存 3、先操作数据库还是缓存3.1 先删除缓存再更新数据库3.2 先更新数据库再删除缓存 4、延时双删4.1 采用读写分离的架构怎么办&#xff1f; 5、利用消息队列进行删除的补偿 1、四种同步策略 想要保证缓…...

MATLAB中ischange函数用法

目录 语法 说明 示例 均值的变化 线性区的变化 矩阵数据 ischange函数的功能是查找数据中的突然变化。 语法 TF ischange(A) TF ischange(A,method) TF ischange(___,dim) TF ischange(___,Name,Value) [TF,S1] ischange(___) [TF,S1,S2] ischange(___) 说明 ​…...

【React + Ant Design】表单如何在前置项未填写时禁止后置项交互并提示

在 react antd 中&#xff0c;对表单做在前置项未填写时禁用后置项交互并提示的效果。 情景 最近有这么个需求&#xff0c;某个业务中&#xff0c;要填写一张表单&#xff0c;其中有这样两项&#xff1a;选择数据连接和选择数据表&#xff0c;数据表是数据连接下所拥有的表。…...

Linux学习之MySQL建表

MySQL查询1 MySQL查询2 表管理 #1. 建库#1&#xff09;库名命名规则仅可以使用数字、字母、下划线、不能纯数字&#xff0c;区分字母大小写&#xff0c;具有唯一性&#xff0c;不可使用MySQL命令或特殊字符#创建数据表时可以查看一下默认的字符集&#xff0c;8.0后创建数据库…...

Redis哨兵集群的介绍及搭建

Redis 是一款开源的、内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。然而&#xff0c;作为一个单点服务&#xff0c;Redis 在面临硬件故障或者网络问题时可能会导致服务不可用。为了解决这个问题&#xff0c;Redis 提供了哨兵模式&#xff0c;一个…...

【zookeeper】zookeeper日常运维

本文将分享一些zookeeper在日常使用中一些维护经验。 zookeeper清理快照 脚本或者命令清理 zookeeper长时间运行&#xff0c;快照逐渐增多可能造成服务器磁盘被占满的情况&#xff0c;但我们不能贸然用rm命令删除快照文件&#xff0c;如果直接删完会导致丢失好多数据&#x…...

【工作记录】MQTT介绍、安装部署及springboot集成@20230912

背景 近期公司可能会有物联网设备相关项目内容&#xff0c;提前对用到的mqtt协议做预研和初步使用。 最初接触到mqtt协议应该是早些年的即时通讯吧&#xff0c;现在已经是物联网设备最热门的协议了。 作为记录&#xff0c;也希望能帮助到需要的朋友。 MQTT介绍 《MQTT 协议规…...

Flask 使用 JWT(一)

下面是一些 JWT 的使用场景: 1、 授权:这是 JWT 最常的使用场景。一旦用户登录,后续的每个请求都必须携带 JWT ,允许用户携带 Token 访问所有的路由、服务器和资源。单点登录时目前使用最广泛的一个场景,因为它开销小并且能够轻易的实现跨域访问。 2、信息交换:JWT Token…...

Oracle(1):Oracle简介

1 什么是 ORACLE ORACLE 数据库系统是美国 ORACLE 公司&#xff08;甲骨文&#xff09;提供的以分布式数据库为核心的一组软件产品&#xff0c;是目前最流行的客户/服务器(CLIENT/SERVER)或B/S 体系结构的数据库之一。 ORACLE 通常应用于大型系统的数据库产品。 ORACLE 数据…...

计算机网络篇之IP地址

计算机网络篇之IP地址 文章目录 计算机网络篇之IP地址概括IPv4地址IPv6地址分配总结 概括 IP地址是计算机网络中用于标识和定位设备的一组数字&#xff0c;IP地址分为IPv4和IPv6两种格式 IPv4地址 IPv4地址是32位的二进制数&#xff0c;通常表示为四个用点分隔的十进制数&am…...

webrtc-m79-测试peerconnectionserver的webclient-p2p-demo

1 背景 webrtc的代码中有peerconnectionclient和peerconnectionserver的例子&#xff0c;但是没有对应的web端的例子&#xff0c;这里简单的写了一个测试例子&#xff0c;具体如下&#xff1a; 2 具体操作 2.1 操作流程 2.2 测试效果 使用webclient与peerconnectionclient的…...

C#,《小白学程序》第十五课:随机数(Random)第二,统计学初步,数据统计的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十五课&#xff1a;随机数&#xff08;Random&#xff09;第二&#xff0c;统计学初步&#xff0c;数据统计的计算方法与代码 /// 用随机数做简单的统计并用图形显示统计结果。 /// </summary> /// <param name&q…...

C# 子类如何访问子类的方法(同一父类)

在继承关系中&#xff0c;子类可以通过创建另一个子类的对象来访问其方法。下面是一个示例&#xff0c;展示了子类如何访问另一个子类的方法&#xff1a; public class Animal {public virtual void Speak(){Console.WriteLine("我是动物。");} }public class Cat :…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

页面渲染流程与性能优化

页面渲染流程与性能优化详解&#xff08;完整版&#xff09; 一、现代浏览器渲染流程&#xff08;详细说明&#xff09; 1. 构建DOM树 浏览器接收到HTML文档后&#xff0c;会逐步解析并构建DOM&#xff08;Document Object Model&#xff09;树。具体过程如下&#xff1a; (…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...