SpringBoot -拦截器Interceptor、过滤器 Filter 及设置
Spring Boot拦截器(Interceptor)的概念
- 在Spring Boot中,拦截器是一种AOP的实现方式。它主要用于<font style="color:#DF2A3F;">拦截请求</font>,在请求处理之前和之后执行特定的代码逻辑。与过滤器不同的是,拦截器更侧重于对Spring MVC中的<font style="color:#DF2A3F;">控制器(Controller)</font>进行拦截,能够访问到Spring MVC上下文中的对象,比如获取请求的处理器(Handler)信息、模型(Model)和视图(View)相关信息等。
创建拦截器类
- 要创建拦截器,需要实现`HandlerInterceptor`接口。这个接口有三个方法:* `<font style="color:#DF2A3F;">preHandle()</font>`:在请求处理之前调用。可以进行权限验证、日志记录等操作。如果返回`false`,则请求被中断,不会继续执行后续的处理器(Controller)方法;如果返回`true`,则请求继续传递。* `<font style="color:#DF2A3F;">postHandle()</font>`:在请求处理之后,视图渲染之前调用。可以对模型(Model)和视图(View)进行修改等操作。* `<font style="color:#DF2A3F;">afterCompletion()</font>`:在整个请求完成后(包括视图渲染后)调用。主要用于资源清理等操作。
- 例如,创建一个简单的拦截器来记录请求处理时间:RequestTimeInterceptor对象
public class RequestTimeInterceptor implements HandlerInterceptor {private Date startTime;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {startTime = new Date();return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {Date endTime = new Date();System.out.println("Request processing time: " + (endTime.getTime() - startTime.getTime()) + "ms");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 可以在这里进行资源清理等操作}
}
配置拦截器
方式一:通过实现WebMvcConfigurer接口
- 创建一个配置类,实现`WebMvcConfigurer`接口。
- 在`addInterceptors`方法中添加拦截器并配置拦截路径。
- 例如:
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RequestTimeInterceptor()).addPathPatterns("/**");}
}
上述代码中,addInterceptor方法添加了
RequestTimeInterceptor拦截器,
addPathPatterns方法指定了拦截的路径为所有路径(
/**`)。
- 方式二:通过扩展WebMvcConfigurationSupport类(不推荐,可能会覆盖Spring Boot的默认配置)
- 创建一个配置类,继承自
WebMvcConfigurationSupport
。 - 重写
addInterceptors
方法来配置拦截器。 - 例如:
- 创建一个配置类,继承自
public class InterceptorConfiguration extends WebMvcConfigurationSupport {@Overrideprotected void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new RequestTimeInterceptor()).addPathPatterns("/**");}
}
- 不过这种方式可能会导致Spring Boot自动配置的一些Web相关的配置失效,如静态资源处理等,所以一般推荐使用第一种方式。
拦截器的执行顺序
- 当有多个拦截器时,它们的执行顺序是按照在`InterceptorRegistry`中添加的顺序来执行的。先添加的拦截器先执行`preHandle`方法,后执行`postHandle`和`afterCompletion`方法。例如,假设有拦截器`Interceptor1`和`Interceptor2`,配置如下:
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new Interceptor1()).addPathPatterns("/**");registry.addInterceptor(new Interceptor2()).addPathPatterns("/**");}
}
- 在这个例子中,`Interceptor1`的`preHandle`方法会先于`Interceptor2`的`preHandle`方法执行。而`Interceptor2`的`postHandle`和`afterCompletion`方法会先于`Interceptor1`的相应方法执行。
过滤器 Filter 的概念
- 在 Spring Boot 中,过滤器是一种用于拦截和处理请求和响应的组件。它可以在请求到达控制器(Controller)之前进行预处理,例如验证请求头、验证用户身份等,也可以在响应返回客户端之前进行后处理,例如修改响应头、添加日志信息等。过滤器可以对多个请求和响应进行统一的处理,是实现横切关注点(如安全、日志记录等)的重要手段。
实现Filter接口,并使用@WebFilter注解(原生servlet配置方式)
- **使用注解方式(推荐)**:- 在Spring Boot中,更方便的是使用`@WebFilter`注解来创建过滤器。例如:- ```java@WebFilter(urlPatterns = "/*")public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化方法,在过滤器初始化时调用,可以进行一些初始化操作,如加载配置文件等}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 过滤方法,在这里可以对请求进行处理,然后决定是否将请求传递给下一个过滤器或控制器// 例如,可以在这里检查请求头中的令牌(Token)是否有效filterChain.doFilter(servletRequest, servletResponse);// 在调用filterChain.doFilter后,可以对响应进行处理}@Overridepublic void destroy() {// 销毁方法,在过滤器销毁时调用,可以进行一些资源释放等}}
- 其中
@WebFilter(urlPatterns = "/*")
注解用于指定过滤器要拦截的 URL 模式,/*
表示拦截所有的请求路径。 - 自动配置使用@WebFilter注解的过滤器:
- 需要在 Spring Boot 的主应用程序类上添加
@ServletComponentScan
注解,这样 Spring Boot 才能扫描到过滤器并自动进行配置。例如:
- 需要在 Spring Boot 的主应用程序类上添加
@SpringBootApplication
@ServletComponentScan
public class MySpringBootApp {public static void main(String[] args) {SpringApplication.run(MySpringBootApp.class, args);}
}
- 手动配置(通过
FilterRegistrationBean
):- 有时候可能需要更灵活的配置,例如设置过滤器的执行顺序、添加初始化参数等。可以通过
FilterRegistrationBean
对象 来手动配置过滤器。例如: <font style="color:rgb(38, 38, 38);background-color:rgb(242, 242, 247);">FilterRegistrationBean对象可以:</font>
- 设置实际过滤器 setFilter()
- 设置过滤器名 setName(“myFilter”);
- 设置过滤路径 addUrlPatterns(“/*”);
- 设置优先级 setOrder(1);
- 有时候可能需要更灵活的配置,例如设置过滤器的执行顺序、添加初始化参数等。可以通过
@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<MyFilter> myFilterRegistration() {FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();registrationBean.setFilter(new MyFilter());registrationBean.addUrlPatterns("/*");registrationBean.setName("myFilter");registrationBean.setOrder(1); // 设置过滤器的执行顺序,数字越小越先执行return registrationBean;}
}
过滤器链(Filter Chain)
- 当有多个过滤器时,它们会形成一个过滤器链。请求会依次经过每个过滤器,每个过滤器都可以对请求进行处理,然后决定是否将请求传递给下一个过滤器。在`doFilter`方法中,通过调用`filterChain.doFilter(servletRequest, servletResponse)`来将请求传递给下一个过滤器或控制器。如果某个过滤器没有调用这个方法,那么请求就会被截断,后续的过滤器和控制器都不会收到这个请求。同样,在响应返回时,也会按照相反的顺序经过各个过滤器,每个过滤器可以对响应进行处理。例如,假设有两个过滤器`Filter1`和`Filter2`,请求首先会到达`Filter1`,`Filter1`处理后传递给`Filter2`,`Filter2`处理后传递给控制器;响应返回时,先经过`Filter2`,再经过`Filter1`,最后返回给客户端。
**1.**通过xml文件配置过滤器链:
* 创建两个过滤器:CharacterEncodingFilter、LoggingFilter
public class CharacterEncodingFilter implements Filter {private String encoding;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {encoding = filterConfig.getInitParameter("encoding");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {servletRequest.setCharacterEncoding(encoding);filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {// 可以在这里进行资源释放等操作}
}
public class LoggingFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("Request received at: " + new Date());filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}
}
* **配置过滤器链(在 web.xml 中)*** 在这个配置中,`LoggingFilter`会应用到所有的请求(`/*`)。`CharacterEncodingFilter`会应用到名为`MyServlet`的 Servlet。当请求到来时,会先经过`LoggingFilter`,然后根据请求的目标是`MyServlet`时,再经过`CharacterEncodingFilter`。
<filter><filter - name>LoggingFilter</filter - name><filter - class>com.example.filters.LoggingFilter</filter - class>
</filter>
<filter - mapping><filter - name>LoggingFilter</filter - name><url - pattern>/*</url - pattern>
</filter - mapping><filter><filter - name>CharacterEncodingFilter</filter - name><filter - class>com.example.filters.CharacterEncodingFilter</filter - class><init - param><param - name>encoding</param - name><param - value>UTF - 8</param - value></init - param>
</filter>
<filter - mapping><filter - name>CharacterEncodingFilter</filter - name><servlet - name>MyServlet</servlet - name>
</filter - mapping>
- 上述代码中,首先定义了一个名为
CharacterEncodingFilter
的过滤器,并且通过<init - param>
标签设置了一个初始化参数encoding
为UTF - 8
。然后通过<filter - mapping>
标签将这个过滤器应用到所有的请求(/*
)。当请求到来时,这个过滤器会设置请求的字符编码为UTF - 8
,然后将请求传递给下一个过滤器或者目标资源。
**2.**使用注解方式(Servlet 3.0+)实现过滤器链
- 当有多个注解式过滤器时,过滤器的执行顺序是按照类名的字典序来确定的。如果需要更精确地控制顺序,可以使用`@javax.annotation.Priority`注解来指定优先级。数字越小,优先级越高。
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.annotation.Priority;
import java.io.IOException;@WebFilter(filterName = "AuthFilter", urlPatterns = "/*")
@Priority(1)
public class AuthFilter implements Filter {//...
}@WebFilter(filterName = "AnotherFilter", urlPatterns = "/*")
@Priority(2)
public class AnotherFilter implements Filter {//...
}
DelegatingFilterProxyRegistrationBean 对象代理过滤器。
DelegatingFilterProxyRegistrationBean
是 Spring Boot 中用于注册一个代理过滤器(DelegatingFilterProxy
)的配置类。它主要用于将一个基于 Servlet 的过滤器集成到 Spring 的应用上下文中,使得这个过滤器能够利用 Spring 的特性,如依赖注入、配置属性等。- 这个类在将传统的 Servlet 过滤器与 Spring 应用进行整合时非常有用。例如,在一些安全认证过滤器或者日志记录过滤器的场景下,通过它可以更好地管理和配置这些过滤器,让它们能够从 Spring 的环境配置(如配置文件、环境变量等)中获取必要的参数,并且能够方便地与 Spring 管理的其他组件(如服务层组件、数据源等)进行交互。
·配置**DelegatingFilterProxyRegistrationBean**
假设我们有一个自定义的过滤器MyFilter
,并且希望通过DelegatingFilterProxyRegistrationBean
来注册它,使其能够与 Spring 应用上下文集成。
1**.创建一个过滤器:MyFilter**
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化过滤器,这里可以获取初始化参数等操作}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 执行过滤操作,例如检查请求头、验证用户身份等filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {// 销毁过滤器,释放资源}
}
2.然后,在Spring Boot的配置类中注册DelegatingFilterProxyRegistrationBean
:
@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<DelegatingFilterProxy> myFilterRegistration() {FilterRegistrationBean<DelegatingFilterProxy> registrationBean = new FilterRegistrationBean<>();DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy("myFilter");registrationBean.setFilter(delegatingFilterProxy);registrationBean.addUrlPatterns("/*");return registrationBean;}@Bean(name = "myFilter")public MyFilter myFilter() {return new MyFilter();}
}
- 在上述配置中,首先创建了一个
DelegatingFilterProxyRegistrationBean
,并将一个DelegatingFilterProxy
实例设置为其过滤器。DelegatingFilterProxy
的构造函数参数"myFilter"
是要在 Spring 应用上下文中查找的真正过滤器 Bean 的名称。然后,通过addUrlPatterns("/*")
设置了过滤器拦截的 URL 模式为所有请求。同时,还通过@Bean(name = "myFilter")
方法定义了真正的过滤器MyFilter
,这样DelegatingFilterProxy
就能在 Spring 应用上下文中找到它并进行委托。
DelegatingFilterProxyRegistrationBean的优点:
1 .灵活性高,它允许过滤器成为 Spring 的 Bean,从而可以利用 Spring 的各种功能,
2 .便与维护和管理。有多个过滤器需要集成和管理。
相关文章:
SpringBoot -拦截器Interceptor、过滤器 Filter 及设置
Spring Boot拦截器(Interceptor)的概念 - 在Spring Boot中,拦截器是一种AOP的实现方式。它主要用于<font style"color:#DF2A3F;">拦截请求</font>,在请求处理之前和之后执行特定的代码逻辑。与过滤器不同的…...

C++小问题
怎么分辨const修饰的是谁 是限定谁不能被改变的? 在C中,const关键字的用途和位置非常关键,它决定了谁不能被修改。const可以修饰变量、指针、引用等不同的对象,并且具体的作用取决于const的修饰位置。理解const的规则能够帮助我们…...
avcodec_alloc_context3,avcodec_open2,avcodec_free_context,avcodec_close
avcodec_alloc_context3 是创建编解码器上下文,需要使用 avcodec_free_context释放 需要使用avcodec_free_context 释放 /** * Allocate an AVCodecContext and set its fields to default values. The * resulting struct should be freed with avcodec_free_co…...

强化学习的几个主要方法(策略梯度、PPO、REINFORCE实现等)(下)
由于平台字数限制,上文:https://blog.csdn.net/ooblack/article/details/144198538 4. PPO算法 近端策略优化(proximal policy optimization,PPO)算法是OpenAI的默认强化学习算法,在RLHF中也用到了这个算…...

计算机网络:IP协议详细讲解
目录 前言 一、IP网段划分 二、IP报头 三、解决IP地址不足-->NAT技术 前言 在之前,我们学习了传输层中的TCP和UDP,重点是TCP协议,他帮我们解决具体到主机的哪个应用(端口)、传输的可靠(序列号、校验和…...

2024信创数据库TOP30之华为Gauss DB
近日,由DBC联合CIW/CIS共同发布的“2024信创数据库TOP30”榜单正式揭晓,汇聚了国内顶尖的数据库企业及其产品,成为展示中国信创领域技术实力与发展潜力的重要平台。在这份榜单中,华为的GaussDB凭借其卓越的技术实力、广泛的行业应…...

在线家具商城基于 SpringBoot:设计模式与实现方法探究
第3章 系统分析 用户的需求以及与本系统相似的在市场上存在的其它系统可以作为系统分析中参考的资料,分析人员可以根据这些信息确定出本系统具备的功能,分析出本系统具备的性能等内容。 3.1可行性分析 尽管系统是根据用户的要求进行制作,但是…...
九、Spring Boot集成Spring Security之授权概述
文章目录 往期回顾:Spring Boot集成Spring Security专栏及各章节快捷入口前言一、授权概述二、用户权限三、用户授权流程三、Spring Security授权方式1、请求级别授权2、方法级别授权 往期回顾:Spring Boot集成Spring Security专栏及各章节快捷入口 Spr…...
python之Flask入门—路由参数
语法: /routerName/<string:parameter_name> 其中:routerName代表路由名称<>中的string是参数类型,parameter_name为参数名称 参数类型: (1) string 接收任何没有斜杠(/&#x…...
txt地图格式处理
1、txt地图格式 [属性描述] 坐标系2000国家大地坐标系 几度分带3 投影类型高斯克吕格 计量单位米 带号38 精度0.001 转换参数,,,,,, [地块坐标] 5,475.888,1,测试地块1,面,J50G077061,公路用地,地下, J1,1,113.22222222222222,23.129111721551794 J2,1,113.2722314…...

《数据挖掘:概念、模型、方法与算法(第三版)》
嘿,数据挖掘的小伙伴们!今天我要给你们介绍一本超级实用的书——《数据挖掘:概念、模型、方法与算法》第三版。这本书是数据挖掘领域的经典之作,由该领域的知名专家编写,系统性地介绍了在高维数据空间中分析和提取大量…...
GitLab CVE-2024-8114 漏洞解决方案
漏洞 ID 标题严重等级CVE ID通过 LFS 令牌提升权限高CVE-2024-8114 GitLab 升级指南GitLab 升级路径查看版本漏洞查询 漏洞解读 此漏洞允许攻击者使用受害者的个人访问令牌(PAT)进行权限提升。影响从 8.12 开始到 17.4.5 之前的所有版本、从 17.5 开…...
request和websocket
当然,可以为你详细介绍 FastAPI 中的 Request 对象。Request 对象在 FastAPI 中扮演着重要的角色,负责封装来自客户端的 HTTP 请求信息。了解 Request 对象的使用方法和属性,有助于你更高效地处理请求数据、访问请求上下文以及进行各种操作。…...

一键生成后端服务,MemFire Cloud重新定义开发效率
作为开发者,特别是独立开发者和小团队成员,大家都知道开发的最大难题之一就是搭建后端服务。要让一个应用从零开始,除了前端的开发工作外,还需要考虑数据库、接口、认证、存储等等一系列繁琐的后台工作。而MemFire Cloud这款神器&…...

短视频矩阵的营销策略:批量混剪实现高效传播
在当今的商业环境中,短视频营销已成为企业获得市场份额的关键策略。随着消费者注意力的分散,传统营销方法的效果逐渐减弱。因此,短视频营销的重要性不言而喻。通过短视频,品牌能够以更为生动和直观的方式传递信息,从而…...

朗迪锋亮相2024人因工程与智能系统交互国际会议
2024年11月28日至30日,2024人因工程与智能系统交互国际会议在深圳隆重举办。此次大会以推动我国人因工程学科发展为目标,致力于加强国际学术交流,深入探讨人工智能时代的智能系统交互,旨在培育新质生产力,助力经济社会…...

spring boot3.3.5 logback-spring.xml 配置
新建 resources/logback-spring.xml 控制台输出颜色有点花 可以自己更改 <?xml version"1.0" encoding"UTF-8"?> <!--关闭文件扫描 scanfalse --> <configuration debug"false" scan"false"><springProperty …...

Proteus8.17下载安装教程
Proteus是一款嵌入式系统仿真开发软件,实现了从原理图设计、单片机编程、系统仿真到PCB设计,真正实现了从概念到产品的完整设计,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,能够帮助用…...
一次Kafka启动失败引出的问题
背景 Some time,有个现场童鞋说咱的Kafka实例有个broker一直crash,还截图给我看了,大致是Kafka启动加载topic分区日志文件的时候,然后就没了,连个WARN都没有。当然,光看这个截图咱啥都不知道,因…...
mysql 查询所有的触发器
SELECTTRIGGER_SCHEMA AS Database,TRIGGER_NAME AS Trigger,EVENT_OBJECT_TABLE AS Table,EVENT_MANIPULATION AS Event,ACTION_STATEMENT AS Statement FROMinformation_schema.TRIGGERS;创建触发器遇到报错: You do not have the SUPER privilege and binary lo…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...