Spring 常用的三种拦截器详解

news/2024/9/8 11:12:53/文章来源:https://www.cnblogs.com/wenbochang/p/18327158

前言

在开发过程中,我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 AOP、 Interceptor 、 Filter,但其实很多人并不知道什么时候用AOP,什么时候用Interceptor,什么时候用Filter,也不知道其拦截顺序,内部原理。今天我们详细介绍一下这三种拦截器。

拦截器顺序

我们现在有一个controller接口,叫做test,现在我们在项目有定义了三个拦截器,其顺序如下

Filter(before) > Interceptor(before) > AOP(before) > test方法 > AOP(after) > Interceptor(after) > Filter(after)

具体流程如下两幅图片。

所以有时候我们使用不了AOP/Interceptor, 只能使用Filter。

  • 比如我们现在是一个Get请求,但是别人却发送了一个Post请求,这时候只有Filter才能拦截,只能使用Filter.
  • 又比如我们在Interceptor获取了请求参数以后,因为是一个流,后面controller就会获取不到,我们一般会采用包装类来实现重复读取。但假如我们直接使用AOP就完全可以避免这个问题了。

类似的例子比较多,所以我们应该知其然,也要知其所以然。下面我们介绍一下三种拦截器的具体用法。

Filter拦截器

filter是servlet层面的提供拦截器,和spring无关。只是说现在spring/springboot一统江湖,很多项目在spring的基础上面使用filter。那我们如果在spring项目中使用filter拦截器呢

@Slf4j
public class FirstFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {log.info("FirstFilter before doFilter");filterChain.doFilter(servletRequest, servletResponse);}
}@Slf4j
public class SecondFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {log.info("SecondFilter before doFilter");filterChain.doFilter(servletRequest, servletResponse);}
}@Slf4j
@Configuration
public class FilterConfig {@Beanpublic FilterRegistrationBean firstFilter() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new FirstFilter());registration.addUrlPatterns("/*");registration.setName("FirstFilter");// 数字越小,优先级越高registration.setOrder(1);return registration;}@Beanpublic FilterRegistrationBean secondFilter() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new SecondFilter());registration.addUrlPatterns("/*");registration.setName("SecondFilter");// 数字越大,优先级越低registration.setOrder(2);return registration;}}

输出结果

FirstFilter before doFilter

SecondFilter before doFilter

Interceptor拦截器

Interceptor是springmvc给我们提供的拦截器,只有在sotingmvc中才可以使用

@Slf4j
@Component
public class FirstInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {log.info("FirstInterceptor preHandle");return true;}
}@Slf4j
@Component
public class SecondInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {log.info("SecondInterceptor preHandle");return true;}}@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate FirstInterceptor firstInterceptor;@Autowiredprivate SecondInterceptor secondInterceptor;// 配置拦截规则public void addInterceptors(InterceptorRegistry registry) {// 按照注册的顺序,依次执行registry.addInterceptor(firstInterceptor).addPathPatterns("/**").excludePathPatterns("/task/**");registry.addInterceptor(secondInterceptor).addPathPatterns("/**").excludePathPatterns("/spring/**");}
}

输出结果

FirstInterceptor preHandle

SecondInterceptor preHandle

AOP拦截器

AOP是我们非常常用的拦截器,织入点,有before,after,around等,我们今天以around为例

@Aspect
@Component
public class LoggerAOP {@Pointcut("execution (public * com.xxx.controller..*(..))")public void pointcutLogger() {}@Around("pointcutLogger()")public Object methodAround(ProceedingJoinPoint joinPoint) throws Throwable {try {logger.info("request className = {}, method = {}, ip = {}, param = {}", className, methodName, ip, param);resp = joinPoint.proceed();long duration = stopwatch.elapsed(TimeUnit.MILLISECONDS);logger.info("response className = {}, method = {}, resp = {}, cost = {}ms", className, methodName, buildResp(resp), duration);}catch (Throwable e) {logger.error("logger request className = {}, method = {} fail message = {} ",className, methodName, e.getMessage(), e);throw e;}return resp;}
}

最后

我们介绍了一下spring中,常用的三种拦截器,以及他们在springboot中如何使用。

最后给大家出一个小作业,如果把上面三个拦截器放到一个项目中,他会输出什么顺序呢?

[INFO  2024-07-27 16:01:52.146] [http-nio-8099-exec-2] [] - [FirstFilter.doFilter:17] [FirstFilter before doFilter]
[INFO  2024-07-27 16:01:52.146] [http-nio-8099-exec-2] [] - [SecondFilter.doFilter:17] [SecondFilter before doFilter]
[INFO  2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [] - [FirstInterceptor.preHandle:18] [FirstInterceptor preHandle]
[INFO  2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [] - [SecondInterceptor.preHandle:18] [SecondInterceptor preHandle]
[INFO  2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [cdc644d0-afdf-4283-bf52-fc5fdd217746] - [LoggerAOP.methodAround:52] [request className = TestController, method = testController, ip = 0:0:0:0:0:0:0:1, param = [null]][INFO  2024-07-27 16:01:52.149] [http-nio-8099-exec-2] [cdc644d0-afdf-4283-bf52-fc5fdd217746] - [TestController.testController:57] [main process][INFO  2024-07-27 16:01:52.149] [http-nio-8099-exec-2] [cdc644d0-afdf-4283-bf52-fc5fdd217746] - [LoggerAOP.methodAround:62] [response className = TestController, method = testController, resp = "ok", cost = 0ms]

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lambda、LINQ

1.Lambda表达式的使用示例如下:2.Linq示例:

并发容器

Java 的并发集合容器提供了在多线程环境中高效访问和操作的数据结构。这些容器通过内部的同步机制实现了线程安全,使得开发者无需显式同步代码就能在并发环境下安全使用,比如说:ConcurrentHashMap、阻塞队列和 CopyOnWrite 容器等。 java.util 包下提供了一些容器类(集合框…

win10运行交互题

这是题目给的 题目要求输入的编译命令g++ -O2 -o grader grader.cpp ramen.cpp 在\(DEV\)下是运行不了的 系统的\(CMD\)也是不行的 但我们可以用\(DEV\)中的\(system\)函数运行 int main() {system("g++ -O2 -o grader grader.cpp ramen.cpp"); return 0; }运行前在\…

15、flask-模型-models-表的操作-分页paginate()

paginate()的属性属性名 说明items 返回当前页的内容列表has_next 是否还有下一页has_prev 是否还有上一页next(error_out=False) 返回下一页的pagination对象prev(error_out=False) 返回上一页的Pagination对象page 当前页的页码pages 总页数per_page 每页显示的数量prev_num …

01-从WordCount程序理解Spark术语及术语间的关系

1. 应用程序(Application) 通过下面的代码设置应用程序名称,设置后再UI中可以看到相应的名称。 //1.设置Application的名称 val conf = new SparkConf() conf.setAppName("WordCount") conf.setMaster("local")2. Job Job由scala的执行算子生成,每个执…

leetcode-5

题目: 给你一个字符串 s,找到 s 中最长的 回文子串 示例 1:输入:s = "babad"  输出:"bab"  解释:"aba" 同样是符合题意的答案。 示例 2:输入:s = "cbbd"   输出:"bb" 提示: 1 <= s.length <= 1000…

Uniapp 之手写签名

一、效果图二、代码示例 qianming.jsexport const qianming = {data() {return {windowWidth: 0,pixelRatio: 0,context: null,points: [],oldPoints: [],qm_width: 280,qm_height: 120,qm_img: }},methods: {qm_start() {const systemInfo = uni.getSystemInfoSync()this.wind…

代码随想录day11 || 150 逆表达式求值 239 滑动窗口最大值 347 前k最高频元素

150 逆波兰表达式计算func evalRPN(tokens []string) int {// 自己想是真的想不出来,看了视频之后有了思路// 本质上逻辑就是遇到数字入栈,遇到运算符号 出栈两个元素然后计算再入栈,最终就是计算结果stack := Constructor()for _, val := range tokens{// 如果数字入栈if i…

计算机组成与体系结构-校验码

奇偶校验码 奇偶校验是一种简单有效的校验方法,这种方法通过在编码中增加一位校验位来使编码中1的个数为奇数(奇校验)或者为偶数(偶校验),只能发现奇数个数据位 出错的情况.循环冗余校验码 CRC(Cyclic RedundancyCheck)循环冗余校验是一种常用的错误检测技术,用于在数据传输…

CAD快捷键命令大全(最全)

勇者无惧,强者无敌。

电影《抓娃娃》迅雷/百度云下载[超清版BT种子][MP4/2.89GB]分享

电影《抓娃娃》是一部由闫非、彭大魔联合执导,沈腾、马丽领衔主演的喜剧电影。该片于2024年7月16日在中国大陆正式上映,以其独特的剧情设定和深刻的主题探讨,迅速吸引了广大观众的关注。影片不仅延续了“沈马组合”一贯的幽默风格,更在喜剧外壳下包裹了深刻的教育主题,让人…

PWM波形生成

背景 方法 定时器 (1)高级定时器timer1, timer8以及通用定时器timer9, timer10, timer11的时钟来源是APB2总线 (2)通用定时器timer2~timer5,通用定时器timer12~timer14以及基本定时器timer6,timer7的时钟来源是APB1总线 (3)当APB1和APB2分频数为1的时候,TIM1、TIM8~TIM…