【Springboot】Filter 过滤器的使用
一、基本介绍
过滤器 Filter 作为 Java 三大器之一,在 Java Web 的使用中有很高的地位。所谓过滤器,就是实现了 javax.servlet.Filter 接口的服务器端程序,就是对事物进行过滤的。在 Web 中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权限管理,过滤敏感词汇等。
使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行预处理并生成响应,最后Filter再对服务器响应进行后处理。
二、过滤器原理
当我们使用过滤器时,过滤器会对游览器的请求进行过滤,过滤器可以动态的分为 3 个部分,1. 放行之前的代码,2. 放行,3. 放行后的代码,这 3 个部分分别会发挥不同作用。
- 第一部分代码会对游览器请求进行第一次过滤,在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest。
-
第二部分根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据,如果还有过滤器,那么就继续交给下一个过滤器。
-
第三部分在 HttpServletRequest 到达客户端之前,拦截 HttpServletResponse,对返回的 Web 资源再次进行过滤处理。
我们使用过滤器,也就是说,不止请求会经过过滤器,我们的响应也会经过过滤器。
三、过滤器的作用
* Examples that have been identified for this design are* 1) Authentication Filters, 即用户访问权限过滤* 2) Logging and Auditing Filters, 日志过滤,可以记录特殊用户的特殊请求的记录等* 3) Image conversion Filters,图像转换过滤器* 4) Data compression Filters ,数据转换* 5) Encryption Filters ,安全加密* 6) Tokenizing Filters ,词法分析* 7) Filters that trigger resource access events ,资源访问事件触发过滤器* 8) XSL/T filters * 9) Mime-type chain Filter ,文件类型链过滤器
四、过滤器(Filter)接口
我们学习过滤器,肯定就要先看一下官方给我们提供的过滤器接口。下面我们使用 Idea 来查看 Filter。
Filter 有如下几个方法:
- void init(FilterConfig filterConfig) 用于完成过滤器的初始化。
-
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 实现过滤功能,将该方法对每个请求增加额外的处理。
-
void destroy() 用于过滤器销毁前,完成某些资源的回收。
五、使用过滤器(Filter)
先自定义 FirstFilter 类实现 Filter 接口:
public class FirstFilter implements Filter {@Override public void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig); System.out.println("--------FirstFilter 初始化完成-------"); }@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("------对 First request 进行过滤 --------");//下面这行代码就是放行 filterChain.doFilter(servletRequest, servletResponse); System.out.println("------对 First response 进行过滤 --------");}@Override public void destroy() {Filter.super.destroy(); System.out.println("firstFilter 已销毁"); }}
再自定义 SecondFilter 类实现 Filter 接口:
public class SecondFilter implements Filter {@Override public void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig); System.out.println("--------SecondFilter 初始化完成-------"); }@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("------对 Second request 进行过滤 --------");//下面这行代码就是放行filterChain.doFilter(servletRequest, servletResponse); System.out.println("------对 Second response 进行过滤 --------");}@Override public void destroy() {Filter.super.destroy(); System.out.println("SecondFilter 已销毁"); }}
再修改 WebConfig 配置类:
@Configuration
public class WebConfig {@Bean public FilterRegistrationBean firstFilterRegistrationBean() {FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>(); // 对哪些路径进行过滤filterFilterRegistrationBean.addUrlPatterns("/*"); filterFilterRegistrationBean.setOrder(1); // 设置优先级 ,数字越小,优先级越高FirstFilter filter = new FirstFilter(); // 绑定过滤器 filterFilterRegistrationBean.setFilter(filter); return filterFilterRegistrationBean; }@Bean public FilterRegistrationBean secondFilterRegistrationBean() {FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>();filterFilterRegistrationBean.addUrlPatterns("/hello"); filterFilterRegistrationBean.setOrder(2); // 设置优先级// 绑定过滤器SecondFilter filter = new SecondFilter(); filterFilterRegistrationBean.setFilter(filter); return filterFilterRegistrationBean; }}
启动服务器,然后我们在浏览器中随便输入一个 url 地址进行访问:
浏览器输出:
控制台输出:
------对 request 进行过滤 ---------
------对 response 进行过滤 --------
现在,我们就已经可以得出两个结论了,过滤器并不会管资源是否存在,而只会对配置的拦截路径进行拦截。拦截不仅会对请求进行拦截,而且还会对相应进行拦截。
六、多个 Filter 的执行顺序
上面我们配置了 2 个过滤器,那么我们怎么知道那个过滤器先执行呢?
启动服务器,然后我们浏览器输入 http://localhost:8080/hello 来进行访问,查看控制台输出
------对 First request 进行过滤 --------
------对 Second request 进行过滤 --------
------对 Second response 进行过滤 --------
------对 First response 进行过滤 --------
我们可以看见 FirstFilter 先进行过滤,然后交给 SecondFilter ,然后访问资源,然后 SecondFilter 对响应进行过滤,然后 FirstFilter 对响应进行过滤。图示如下:
七、过滤器(Filter)生命周期
Filter 有三个阶段,分别是初始化,拦截和过滤,销毁。
- 初始化阶段:web 应用程序启动时,web 服务器将创建 Filter 的实例对象,并调用其 init 方法,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作,filter 对象只会创建一次,init 方法也只会执行一次。通过 init 方法的参数,可获得代表当前 filter 配置信息的 FilterConfig 对象(永远只调用一次)
- 拦截和过滤阶段:只要请求资源的路径和拦截的路径相同,那么过滤器就会对请求进行过滤,这个阶段在服务器运行过程中会一直循环,不管第几次,都在调用doGet(),doPost() 方法之前。
- 销毁阶段:当服务器(Tomcat)关闭时,Web 容器调用 destroy 方法销毁 Filter。destroy 方法在 Filter 的生命周期中仅执行一次。在 destroy 方法中,可以释放过滤器使用的资源(永远只调用一次);
八、FilterConfig 和 FilterChain 说明
FilterConfig 和 FilterChain 这2个对象是由服务器 (Tomcat) 在创建和调用 Filter 对象时所传入的,这2个对象十分有用,FilterConfig 对象可以读取我们配置的初始参数,FilterChain 可以实现多个 Filter 之间的连接。
1、FilterConfig
先看一下源码:
public interface FilterConfig {String getFilterName();ServletContext getServletContext();String getInitParameter(String var1);Enumeration<String> getInitParameterNames();
}
里面的方法就 4 个,下面我们分别进行讲解
- getFilterName():获取 filter 的名称
- getServletContext():获取 ServletContext
- getInitparamter(String var1):获取配置的初始参数的值
- getInitParamterNames():获取配置的所有参数名称
2、FilterChain
先看一下源码
public interface FilterChain {void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
}
我们查看源码,可以发现 FilterChain 就只有一个方法,其实这个方法就是用来对拦截进行放行的,如果有多个拦截器,那么就会继续调用下一个 Filter 进行拦截。doFilter 方法需要传入个参数,一个是 ServletRequest,一个是 ServletResponse 参数,这个直接传入进行。
Tomcat 在调用过滤器时,默认就会传入 Request 和 Response,这个参数封装了请求和响应,我们直接使用就行。ServletResquest 和 ServletResponse 可以直接强转成 HttpServletRequest 和 HttpServletResponse,然后使用相应的方法。
将 ServletRequest 转成 HttpServletRequest
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;}
九、参考文档
JavaWeb 过滤器 (Filter) 详解
相关文章:

【Springboot】Filter 过滤器的使用
一、基本介绍 过滤器 Filter 作为 Java 三大器之一,在 Java Web 的使用中有很高的地位。所谓过滤器,就是实现了 javax.servlet.Filter 接口的服务器端程序,就是对事物进行过滤的。在 Web 中的过滤器,当然就是对请求进行过滤&#…...

力扣-461.汉明距离
Method 1 直接比较x,y二进制中的每一位,如果不同则cnt加一,并且x,y每次右移一位 class Solution { public:int hammingDistance(int x, int y) {int cnt 0;while(x > 0 && y > 0) {if((x & 1) ! (y & 1)…...

GEE 18:基于GEE平台的土地荒漠化监测与分析【论文复现】
Desertification 1. 研究背景1.1 参考论文1.2 参数获取1.2.1 NDVI1.2.2 Albedo1.2.3 Normalizing indices1.2.4 Calculating the quantitative relationship1.2.5 Calculating DDI2. GEE2.1 数据2.2 GEE code2.2.1 Study region2.2.2 Reomove cloud for Landsat-82.2.3 Calcula…...

平台系统老板驾驶舱的重要性,我选云表
平台系统老板驾驶舱的重要性在于它是一个集成的管理和分析工具,能够提供对平台系统运行情况的全面和实时的监控、分析和管理功能。以下是平台系统老板驾驶舱的重要性: 老板驾驶舱 该表单可供老板实时把控企业运营情况,包括销售业绩、…...

【SpringMVC篇】探索请求映射路径,Get请求与Post请求
🎊专栏【SpringMVC】 🍔喜欢的诗句:天行健,君子以自强不息。 🎆音乐分享【如愿】 🎄欢迎并且感谢大家指出小吉的问题🥰 文章目录 🌺请求映射路径⭐报错原因⭐解决方法 🌺…...

vqvae简单实战,利用vqvae来提升模型向量表达
最近CV领域各种大模型在图像生成领域大发异彩,比如这两年大火的dalle系列模型。在这些模型中用到一个基础模型vqvae,今天我们写个简单实现来了解一下vqvae的工作原理。vqvae原始论文连接https://arxiv.org/pdf/1711.00937.pdf 1,代码 首先我们…...

idea禁用双击ctrl
Run anything | IntelliJ IDEA Documentation Disable double modifier key shortcuts...

记使用docker部署项目出现问题
我的docker-compose.yml内容如下: version: "3" services:my_server:build: .restart: alwaysdepends_on:mysql:condition: service_startedports:- 9999:9999links:- mysqlmysql:image: mysql:latest # mysql:oraclerestart: alwayscontainer_name: mys…...

EDU挖掘
1.信息搜集2.漏洞挖掘 1.信息搜集 没事干,准备找个证书站挖挖看,没想到碰到一个小通用系统。 看样子还挺多功能可以测, 这里利用F12 查看前端源码js 或者css文件,直接用hunter或者fofa搜索到同一类型的网站。 Hunter语法&#…...

机器人制作开源方案 | 杠杆式6轮爬楼机器人
1. 功能描述 本文示例将实现R281b样机杠杆式6轮爬楼机器人爬楼梯的功能(注意:演示视频中为了增加轮胎的抓地力,在轮胎上贴了双面胶,请大家留意)。 2. 结构说明 杠杆式6轮爬楼机器人是一种专门用于爬升楼梯或不平坦地面…...

报错——warning: ignoring JAVA_HOME=/home/jdk/jdk1.8.0_281; using bundled JDK
我使用了es的8.3.0版本,但es从7.17版本以后不再支持jdk1.8了,需要进行JDK的版本升级,或者降低es的版本。 es和jdk对比版本...
【Java8】java.time 根据日期获取年初年末、月初月末、日初日末
目录 年初年末月初月末3. 日初日末 记录日常开发中的常用的日期转换代码,算是一篇Java 8时间API使用实操的简短总结文。 下文中,都以LocalDateTime为例,在不声明的情况下如下方法一般都适用于Java8中LocalDate、LocalDateTime、OffsetDateTi…...

【LeetCode: 137. 只出现一次的数字 II | 位运算 | 哈希表】
🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…...

「深入探究Web页面生命周期:DOMContentLoaded、load、beforeunload和unload事件」
🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 引言 1. DOMContentLoaded 1.1 属性 1.2 A…...

SpringMVC源码分析(一)启动流程分析
a、SpringMVC 在启动过程中主要做了什么事情? SpringMVC在启动过程中是什么时候解析web.xml文件的,又是什么时候初始化9大内置对象的? <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xml…...

ARM 10.12
设置按键中断,按键1按下,LED亮,再按一次,灭 按键2按下,蜂鸣器响。再按一次,不响 按键3按下,风扇转,再按一次,风扇停 src/key.c #include"key.h"//按键3的配…...

vue-rouer 路由
安装/配置: //进入项目目录:(在搭建项目的时候安装了) cnpm install vue-router --save旧版路由 需要自己配置 //项目中载入,一般在main.js中载入:import VueRouter from vue-routerVue.use(VueRouter)let router new VueRouter({}) //其中配置路径和地址//在Vue中引入:n…...
元数据的前世今生
什么是元数据 元数据(Metadata)是描述数据的数据。它是一组信息,用于描述数据的特征、属性、结构和内容,以便更好地管理、理解、组织和使用数据。让人们能够清楚拥有什么数据、代表什么、源自何处、如何在系统中移动,以及哪些人可以使用源数据,如何使用。 元数据通常包…...

Python实现简易过滤删除数字的方法
嗨喽~大家好呀,这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 如果想从一个含有数字,汉字,字母的列表中滤除仅含有数字的字符, 当然可以采取正则表达式来完成,但是有点太麻烦了…...

软件测试定位bug方法+定位案例(详解)
1、问题bug定位技巧 首先,作为开发也好,测试也好,定位问题有一个总的思路,而这个思路是和数据的走向一致的。 大致是这样: 用户层面问题 -> Web页面/软件界面 -> 中间件 -> 后端服务 -> 代码 -> 数据…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...