【过滤器 vs 拦截器】SpringBoot中过滤器与拦截器:明智选择的艺术(如何在项目中做出明智选择)
文章目录
- SpringBoot 过滤器 vs 拦截器
- 过滤器 (Filter)
- 定义
- 特点
- 使用场景
- 实现步骤
- 创建过滤器类
- 注册过滤器(可选,如果不使用 @WebFilter 注解)
- 拦截器 (Interceptor)
- 定义
- 特点
- 使用场景
- 实现步骤
- 创建拦截器类
- 注册拦截器
- 过滤器与拦截器的比较
- 实际项目中的选择
- 结论
SpringBoot 过滤器 vs 拦截器
在构建Spring Boot应用程序时,开发者经常需要在过滤器(Filters)与拦截器(Interceptors)之间做出选择,尽管两者都能在请求-响应周期中发挥作用,但它们各自有着特定的设计目的和应用场景。下面我们将探讨过滤器与拦截器之间的主要区别,并给出在不同情况下如何合理选用的指导原则。
过滤器 (Filter)
定义
过滤器是Java Servlet API的一部分,用于在请求达到目标资源(如Servlet或JSP页面)之前或在响应从目标资源返回到客户端之后进行预处理或后处理。它们可以被看作是请求和响应的“管道”,允许开发人员执行一些跨切割关注点的操作,如编码转换、添加响应头、身份验证、日志记录等。
特点
- 生命周期管理:过滤器具有初始化(init),过滤(doFilter)和销毁(destroy)的方法,这些方法分别在过滤器创建、每次请求和服务器关闭时调用。
- 执行顺序:过滤器的执行顺序是由部署描述符(web.xml)或等效的Java配置类中定义的过滤器映射所决定的。
- 跨容器:过滤器可以在任何实现了Servlet规范的容器中工作,这意味着它们可以用于任何基于Servlet的Web应用程序,而不仅仅是Spring Boot应用。
- 请求/响应处理:过滤器可以在请求到达目标资源前和响应离开容器后执行操作,这使得它们非常适合处理一些需要在所有请求中都生效的任务。
使用场景
- 安全性:实现身份验证和授权逻辑,确保只有经过验证的用户才能访问某些资源。
- 编码转换:在请求和响应中进行字符集转换,以支持国际化。
- 日志记录:记录每个请求的信息,用于调试和监控应用程序行为。
- 性能监控:测量请求处理时间,以便进行性能分析和优化。
- 资源限制:限制请求频率,防止资源滥用,例如通过实现速率限制功能。
- 响应头添加:自动添加HTTP响应头,如CORS支持或安全相关的头部信息。
实现步骤
在Spring Boot项目中,过滤器可以通过实现javax.servlet.Filter
接口或使用Spring的org.springframework.web.filter.OncePerRequestFilter
来创建,然后在WebSecurityConfigurerAdapter
中配置,或者直接在SpringBootServletInitializer
中注册,以确保它们在应用程序启动时正确加载和初始化。
创建过滤器类
实现 javax.servlet.Filter
接口。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 初始化代码,可选实现System.out.println("Filter initialized");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {// 过滤器逻辑在请求处理前执行System.out.println("Request received at filter");// 继续调用过滤器链,传递请求和响应chain.doFilter(request, response);// 过滤器逻辑在响应处理后执行System.out.println("Response leaving filter");}@Overridepublic void destroy() {// 销毁代码,可选实现System.out.println("Filter destroyed");}
}
注册过滤器(可选,如果不使用 @WebFilter 注解)
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean<MyFilter> loggingFilter(){FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();// 注册自定义过滤器实例registrationBean.setFilter(new MyFilter());// 指定过滤器应用的 URL 模式registrationBean.addUrlPatterns("/*");// 设置过滤器优先级,值越低优先级越高registrationBean.setOrder(1);return registrationBean;}
}
拦截器 (Interceptor)
定义
拦截器是AOP(面向切面编程)概念在Web开发中的具体应用,主要用于在不修改原始代码的情况下增强程序的功能。在Spring Boot框架中,拦截器被广泛应用于处理请求的特定阶段,如在请求到达控制器之前或之后执行某些操作。它提供了一种机制,可以在请求处理的不同阶段执行自定义的代码逻辑。
特点
- 生命周期钩子:拦截器提供了多个钩子方法,如
preHandle()
、postHandle()
和afterCompletion()
,分别在请求处理的开始、结束和完成后调用。 - 动态性:可以通过配置来决定哪些请求会被拦截器处理,而无需修改具体的控制器代码。
- 非侵入性:拦截器的设计使得业务逻辑与横切关注点分离,使得代码更加模块化和可维护。
- 可插拔性:可以根据需要轻松地添加、移除或更改拦截器,而不会影响到现有的业务逻辑。
使用场景
- 权限认证与授权:在请求到达控制器之前检查用户的身份和权限,以确定是否允许访问相应的资源。
- 日志记录:记录请求和响应的详细信息,有助于调试和性能分析。
- 数据预处理:在请求数据到达控制器前进行预处理,如数据转换、校验等。
- 响应修饰:在响应发送给客户端前,可以对响应体进行修改或补充,如添加额外的响应头。
- 性能监控:测量控制器方法的执行时间,监控应用性能。
- 事务管理:在业务逻辑方法执行前后进行事务管理,确保数据的一致性和安全性。
实现步骤
在Spring Boot中,拦截器的实现和注册相对简单。开发者可以创建一个实现了HandlerInterceptor
接口的类,并在配置类中使用@Configuration
和WebMvcConfigurer
接口来注册拦截器。这样,拦截器就能按照定义的规则自动生效,无需手动在每个控制器上添加注解或配置。这种机制使得Spring Boot应用程序能够高效地处理各种请求,并能轻松地扩展其功能,而不会破坏原有的代码结构。
创建拦截器类
实现 HandlerInterceptor
接口。
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 请求处理前逻辑System.out.println("Request intercepted at preHandle");// 返回 true 继续请求,返回 false 中断请求return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {// 请求处理后逻辑System.out.println("Request intercepted at postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 请求处理完成后的逻辑System.out.println("Request intercepted at afterCompletion");}
}
注册拦截器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 注册自定义拦截器实例,并指定拦截的路径模式registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/login", "/register"); // 可以排除某些路径不被拦截}
}
过滤器与拦截器的比较
特性 | 过滤器 (Filter) | 拦截器 (Interceptor) |
---|---|---|
所属规范 | Servlet 规范 | Spring MVC 框架 |
作用范围 | 整个应用程序的所有请求 | 仅限于 Spring MVC 的控制器请求 |
修改请求响应 | 可以直接修改请求和响应 | 通常不直接修改请求和响应 |
配置方式 | 通过 @WebFilter 注解或 FilterRegistrationBean | 通过实现 HandlerInterceptor 并注册 |
典型应用场景 | 认证、日志、压缩响应 | 日志、权限校验、视图处理 |
在实际项目中选择使用过滤器(Filter)还是拦截器(Interceptor),主要取决于你的具体需求和它们各自的特点。以下是一些指导原则,帮助你做出明智的选择:
实际项目中的选择
过滤器(Filter)
-
何时使用
- 当你需要在所有请求的入口处执行代码,而不论请求最终会到达哪个具体的Spring组件时。
- 当你关注的是跨多个应用程序的通用功能,如安全性(如CSRF保护)、编码转换、性能监控、添加响应头等。
- 当你想要在请求到达Spring MVC DispatcherServlet之前或在响应被发送给客户端之后执行代码。
-
优势
- 过滤器在Servlet容器级别运行,这意味着它们适用于所有基于Servlet的Web应用,而不局限于Spring MVC或Spring Boot。
- 过滤器的执行顺序在web.xml或等效的Java配置中明确定义,这提供了清晰的控制流。
拦截器(Interceptor)
-
何时使用
- 当你需要在Spring MVC的请求处理链中添加逻辑,尤其是在请求到达控制器方法前后或在视图渲染前后。
- 当你关心的是与Spring MVC紧密相关的功能,如用户认证、权限检查、日志记录、数据预处理等。
- 当你需要访问Spring MVC的上下文,如模型数据、视图、控制器等。
-
优势
- 拦截器是Spring框架的一部分,可以充分利用Spring的特性,如依赖注入、事务管理等。
- 拦截器的配置更加灵活,你可以选择只对特定的请求路径应用拦截器。
实际考虑因素
- 性能影响:考虑过滤器和拦截器对系统性能的影响。通常,过滤器由于更早地介入请求流程,可能对性能有更大影响。
- 代码耦合度:拦截器更倾向于业务逻辑的紧密集成,而过滤器则更偏向于独立于具体业务逻辑的跨切关注点。
- 维护成本:评估长期维护成本,包括代码的可读性、可测试性和可扩展性。
结论
在SpringBoot应用中,过滤器和拦截器都扮演着重要角色,选择使用哪一种应基于项目需求和它们各自的特点进行权衡。如果需求指向处理所有请求的低层次功能,如编码转换或安全检查,过滤器可能是更优的选择;而如果功能更偏向于Spring MVC的高层次操作,如权限控制或数据预处理,拦截器则更为适合。在实际项目中,我们可能会发现同时利用过滤器和拦截器的情况,以便全面覆盖应用程序的不同方面。记住,没有一成不变的规则,最重要的是根据项目的具体需求和上下文来灵活决定使用哪种机制,以达到最佳的效果。
相关文章:
【过滤器 vs 拦截器】SpringBoot中过滤器与拦截器:明智选择的艺术(如何在项目中做出明智选择)
文章目录 SpringBoot 过滤器 vs 拦截器过滤器 (Filter)定义特点使用场景实现步骤创建过滤器类注册过滤器(可选,如果不使用 WebFilter 注解) 拦截器 (Interceptor)定义特点使用场景实现步骤创建拦截器类注册拦截器 过滤器与拦截器的比较实际项…...

2024-06学习笔记
1.事务与数据库链接的占用 如果用Transactional注解,那在第一次与数据库交互的时候,就会打开数据库链接,再整个方法执行完,才会关闭数据库链接。 即使后边用的事务传播是required_new,那之前的事务也是被挂起,不会被…...

【VUE】封装一个追随鼠标的漂浮组件框架
红色箭头代表鼠标位置,蓝色区域跟随鼠标出现,鼠标进行其他操作的时候,蓝色区域隐藏。 vue全码 <template><divmousemove"updatePosition"mouseleave"hideDiv"class"container":style"{ positi…...
mapstruct与lombok结合使用
问题 如果同时使用mapstruct与lombok,需要多添加一个lombok支持mapstruct的依赖库。 解决 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId> </dependency><dependency><groupId&…...
【SpringBoot】Web开发之URL映射
RequestMapping("/getDataById/{id}") public String getDataById(PathVariable("id") Long id){ return "getDataById:"id; }46 如果URL中的参数名称与方法中的参数名称一致,则可以简化为: RequestMapping("/get…...

对递归的一些理解。力扣206题:翻转链表
今天在刷力扣的时候,在写一道翻转链表的题目的过程中,在尝试使用递归解决该问题的时候,第一版代码却每次都返回的是null,这个错误让我尝试去debug了一下,最终找出了问题,并且让我对递归有了一些更深的理解&…...
Kafka面试三道题
针对Kafka的面试题,从简单到困难,我可以给出以下三道题目: 1. Kafka的基本概念与优势 问题:请简要介绍Kafka是什么,并说明它相比传统消息队列的优势有哪些? 答案: Kafka定义:Apa…...

C/C++编程-算法学习-数字滤波器
数字滤波器 一阶低通滤波器结论推导11. 基本公式推导2. 截止频率 和 采样频率 推导 实现 二阶低通滤波器实现1实现2 一阶低通滤波器 结论 其基本原理基于以下公式: o u t p u t [ n ] α ∗ i n p u t [ n ] ( 1 − α ) ∗ o u t p u t [ n − 1 ] output[n] …...

maven介绍 搭建Nexus3(maven私服搭建)
Maven是一个强大的项目管理工具,它基于项目对象模型(POM:Project Object Model)的概念,通过XML格式的配置文件(pom.xml)来管理项目的构建 Maven确实可以被视为一种工程管理工具或项目自动化构…...

电商项目之如何判断线程池是否执行完所有任务
文章目录 1 问题背景2 前言3 4种常用的方法4 代码4.1 isTerminated()4.2 线程池的任务总数是否等于已执行的任务数4.3 CountDownLatch计数器4.4 CyclicBarrier计数器 1 问题背景 真实生产环境的电商项目,常使用线程池应用于执行大批量操作达到高性能的效果。应用场景…...

【前端 15】Vue生命周期
Vue生命周期 在Vue.js中,了解组件的生命周期对于开发者来说是至关重要的。Vue的生命周期指的是Vue实例从创建到销毁的一系列过程,每个阶段都对应着特定的生命周期钩子(或称为生命周期方法),允许我们在不同的时间点加入…...

PCIe总线-Linux内核PCIe软件框架分析(十一)
1.简介 Linux内核PCIe软件框架如下图所示,按照PCIe的模式,可分为RC和EP软件框架。RC的软件框架分为五层,第一层为RC Controller Driver,和RC Controller硬件直接交互,不同的RC Controller,其驱动实现也不相…...

视觉SLAM第二讲
SLAM分为定位和建图两个问题。 定位问题 定位问题是通过传感器观测数据直接或间接求解位置和姿态。 通常可以分为两类:基于已知地图的定位和基于未知地图的定位。 基于已知地图的定位 利用预先构建的地图,结合传感器数据进行全局定位。SLAM中的全局…...

mysql1055报错解决方法
目录 一、mysql版本 二、 问题描述 三、解决方法 1.方法一(临时) 2.方法二(永久) 一、mysql版本 mysql版本:5.7.23 二、 问题描述 在查询时使用group by语句,出现错误代码:1055…...
Java的@DateTimeFormat注解与@JsonFormat注解的使用对比
Java的DateTimeFormat注解与JsonFormat注解的使用对比 在Java开发中,处理日期和时间格式时,我们经常会使用到DateTimeFormat和JsonFormat注解。这两个注解主要用于格式化日期和时间,但在使用场景和功能上有所不同。本文将详细介绍这两个注解…...

德国云手机:企业移动办公解决方案
在现代商业环境中,移动办公已经成为一种趋势。德国云手机作为一种高效的解决方案,为企业提供了强大的支持。本文将探讨德国云手机如何优化企业的移动办公环境。 一、德国云手机的主要优势 高灵活性 德国云手机具有高度的灵活性,能够根据用户需…...

【React】useState:状态管理的基石
文章目录 一、什么是 useState?二、useState 的基本用法三、useState 的工作原理四、高级用法五、最佳实践 在现代前端开发中,React 是一个非常流行的库,而 useState 是 React 中最重要的 Hook 之一。useState 使得函数组件能够拥有自己的状态…...
商品中心关于缓存热key的解决方案
缓存热key一旦被击穿,流量势必会打到数据库,如果数据库崩了,游戏直接结束。 从两点来讨论:如何监控、如何解决。 如何监控 通过业务评估:比如营销活动推出的商品或者热卖的商品。基于LRU的命令,redis-cl…...

【Python系列】Parquet 数据处理与合并:高效数据操作实践
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

大脑自组织神经网络通俗讲解
大脑自组织神经网络的核心概念 大脑自组织神经网络,是指大脑中的神经元通过自组织的方式形成复杂的网络结构,从而实现信息的处理和存储。这一过程涉及到神经元的生长、连接和重塑,是大脑学习和记忆的基础。其核心公式涉及神经网络的权重更新…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...