前言

在开发过程中,我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 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 {
@Override
public 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 {
@Override
public 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 { @Bean
public FilterRegistrationBean firstFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new FirstFilter());
registration.addUrlPatterns("/*");
registration.setName("FirstFilter");
// 数字越小,优先级越高
registration.setOrder(1);
return registration;
} @Bean
public 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 { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { log.info("FirstInterceptor preHandle");
return true;
}
} @Slf4j
@Component
public class SecondInterceptor implements HandlerInterceptor { @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception { log.info("SecondInterceptor preHandle");
return true;
} } @Configuration
public class InterceptorConfig implements WebMvcConfigurer { @Autowired
private FirstInterceptor firstInterceptor; @Autowired
private 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]

Spring 常用的三种拦截器详解的更多相关文章

  1. Spring Boot实践——三种拦截器的创建

    引用:https://blog.csdn.net/hongxingxiaonan/article/details/48090075 Spring中的拦截器 在web开发中,拦截器是经常用到的功能.它可 ...

  2. AspectCore动态代理中的拦截器详解(一)

    前言 在上一篇文章使用AspectCore动态代理中,简单说明了AspectCore.DynamicProxy的使用方式,由于介绍的比较浅显,也有不少同学留言询问拦截器的配置,那么在这篇文章中,我们来 ...

  3. Window下PHP三种运行方式图文详解,window下的php是不是单进程的?

    Window下PHP三种运行方式图文详解,window下的php是不是单进程的? PHP运行目前为止主要有三种方式: a.以模块加载的方式运行,初学者可能不容易理解,其实就是将PHP集成到Apache ...

  4. python selenium 三种等待方式详解[转]

    python selenium 三种等待方式详解   引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...

  5. C++的三种继承方式详解以及区别

    目录 目录 C++的三种继承方式详解以及区别 前言 一.public继承 二.protected继承 三.private继承 四.三者区别 五.总结 后话 C++的三种继承方式详解以及区别 前言 我发 ...

  6. pytorch的三种量化方式详解

    pytorch的三种量化方式详解 这篇博客详细介绍了pytorch官方教程提到的三种量化方式的原理,详细解释了三种量化方式的区别: 1. 静态量化 :torch.quantize_per_tensor ...

  7. Spring boot 集成三种拦截方式

    三种拦截方式分别为: javax.servlet.Filter org.springframework.web.servlet.HandlerInterceptor org.aspectj.lang. ...

  8. Springboot 过滤器和拦截器详解及使用场景

    一.过滤器和拦截器的区别 1.过滤器和拦截器触发时机不一样,过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的.请求结束返回也是,是在servlet处理完后,返回给前端之前. 2.拦截 ...

  9. SpringMVC拦截器详解[附带源码分析]

    目录 前言 重要接口及类介绍 源码分析 拦截器的配置 编写自定义的拦截器 总结 总结 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门blog:h ...

  10. vmware虚拟机三种网络模式详解_转

    原文来自http://note.youdao.com/share/web/file.html?id=236896997b6ffbaa8e0d92eacd13abbf&type=note 由于L ...

随机推荐

  1. Vue3.0极速入门(三) - 登录demo

    Talk is cheap, Show the code · 在完成npm和vue的环境安装,并了解了基本的目录和文件结构以后,直接写一个带登录和首页的demo做示例,快速了解一个vue工程的创建和基 ...

  2. MySQL配置主从同步过程记录

    今天由于工作需要,配置了一下主从同步,这里记录一下配置过程,以备查阅. 事先度娘了一番,主从同步需要保证主从服务器MySQL版本一致(我的略有差别,主服务器版本5.5.31,从服务器版本5.5.19) ...

  3. 《iOS面试之道》-“串行队列的代码实战” 勘误

    一.原书第一版154页开始讲解串行队列.并发队列.以及在Dispatch_Async.Dispatch_Sync下面的作用 最后一段代码: if(_q == NULL) { _q = dispatch ...

  4. Windows库链接报错

    问题回溯 今天拿到别人已经编译好的库,发现在链接的时候出现了报错 [9/9 12.7/sec] Linking CXX shared module bin\plugins\AsensingPlugin ...

  5. Qt下载、安装及环境搭建

    1  下载 刚开始去的官网下载,需要注册账号,而且还比较麻烦,后来找到了一个安装包的链接,直接下载就好了:http://mirrors.ustc.edu.cn/qtproject/archive/qt ...

  6. python-判断两个序列的成员是否一样

    目的:判断两个序列的成员是否一样,如:list1 = [1, 2],list2 = [2, 1],则两个序列的成员是一样的. 实现:借助集合set()的性质实现. 代码如下: 1 if __name_ ...

  7. react生命周期比较常用的几个

    import React, { Component } from 'react' // 只有在类组件中才有生命周期 export default class App extends Component ...

  8. 操作标签的属性和属性值 table表格

     // 操作标签的属性和属性值         // 特殊的属性           // 可以直接通过 点语法或者[]语法来操作的属性         // id 和 class           ...

  9. kettle从入门到精通 第三十三课 再谈 kettle 表输出 分区/分片

    1.之前第九章有讲过kettle 表输出步骤,里面有简单的提到过表输出步骤里面的表分区设置,这里详细介绍下. 表分区数据:选择此选项可根据"分区"字段中指定的日期字段的值将数据拆分 ...

  10. linux系统下,安装maven教程

    1.下载 官网:https://maven.apache.org/download.cgi 2.上传包 将下载好的maven安装包apache-maven-3.8.6-bin.tar.gz放在磁盘的 ...