经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
Spring 常用的三种拦截器详解
来源:cnblogs  作者:程序员博博  时间:2024/7/29 9:43:11  对本文有异议

前言

在开发过程中,我们常常使用到拦截器来处理一些逻辑。最常用的三种拦截器分别是 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拦截器呢

  1. @Slf4j
  2. public class FirstFilter implements Filter {
  3. @Override
  4. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  5. log.info("FirstFilter before doFilter");
  6. filterChain.doFilter(servletRequest, servletResponse);
  7. }
  8. }
  9. @Slf4j
  10. public class SecondFilter implements Filter {
  11. @Override
  12. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  13. log.info("SecondFilter before doFilter");
  14. filterChain.doFilter(servletRequest, servletResponse);
  15. }
  16. }
  17. @Slf4j
  18. @Configuration
  19. public class FilterConfig {
  20. @Bean
  21. public FilterRegistrationBean firstFilter() {
  22. FilterRegistrationBean registration = new FilterRegistrationBean();
  23. registration.setFilter(new FirstFilter());
  24. registration.addUrlPatterns("/*");
  25. registration.setName("FirstFilter");
  26. // 数字越小,优先级越高
  27. registration.setOrder(1);
  28. return registration;
  29. }
  30. @Bean
  31. public FilterRegistrationBean secondFilter() {
  32. FilterRegistrationBean registration = new FilterRegistrationBean();
  33. registration.setFilter(new SecondFilter());
  34. registration.addUrlPatterns("/*");
  35. registration.setName("SecondFilter");
  36. // 数字越大,优先级越低
  37. registration.setOrder(2);
  38. return registration;
  39. }
  40. }

输出结果

FirstFilter before doFilter

SecondFilter before doFilter

Interceptor拦截器

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

  1. @Slf4j
  2. @Component
  3. public class FirstInterceptor implements HandlerInterceptor {
  4. @Override
  5. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
  6. throws Exception {
  7. log.info("FirstInterceptor preHandle");
  8. return true;
  9. }
  10. }
  11. @Slf4j
  12. @Component
  13. public class SecondInterceptor implements HandlerInterceptor {
  14. @Override
  15. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
  16. throws Exception {
  17. log.info("SecondInterceptor preHandle");
  18. return true;
  19. }
  20. }
  21. @Configuration
  22. public class InterceptorConfig implements WebMvcConfigurer {
  23. @Autowired
  24. private FirstInterceptor firstInterceptor;
  25. @Autowired
  26. private SecondInterceptor secondInterceptor;
  27. // 配置拦截规则
  28. public void addInterceptors(InterceptorRegistry registry) {
  29. // 按照注册的顺序,依次执行
  30. registry.addInterceptor(firstInterceptor)
  31. .addPathPatterns("/**")
  32. .excludePathPatterns("/task/**");
  33. registry.addInterceptor(secondInterceptor)
  34. .addPathPatterns("/**")
  35. .excludePathPatterns("/spring/**");
  36. }
  37. }

输出结果

FirstInterceptor preHandle

SecondInterceptor preHandle

AOP拦截器

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

  1. @Aspect
  2. @Component
  3. public class LoggerAOP {
  4. @Pointcut("execution (public * com.xxx.controller..*(..))")
  5. public void pointcutLogger() {}
  6. @Around("pointcutLogger()")
  7. public Object methodAround(ProceedingJoinPoint joinPoint) throws Throwable {
  8. try {
  9. logger.info("request className = {}, method = {}, ip = {}, param = {}", className, methodName, ip, param);
  10. resp = joinPoint.proceed();
  11. long duration = stopwatch.elapsed(TimeUnit.MILLISECONDS);
  12. logger.info("response className = {}, method = {}, resp = {}, cost = {}ms", className, methodName, buildResp(resp), duration);
  13. }
  14. catch (Throwable e) {
  15. logger.error("logger request className = {}, method = {} fail message = {} ",
  16. className, methodName, e.getMessage(), e);
  17. throw e;
  18. }
  19. return resp;
  20. }
  21. }

最后

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

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

  1. [INFO 2024-07-27 16:01:52.146] [http-nio-8099-exec-2] [] - [FirstFilter.doFilter:17] [FirstFilter before doFilter]
  2. [INFO 2024-07-27 16:01:52.146] [http-nio-8099-exec-2] [] - [SecondFilter.doFilter:17] [SecondFilter before doFilter]
  3. [INFO 2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [] - [FirstInterceptor.preHandle:18] [FirstInterceptor preHandle]
  4. [INFO 2024-07-27 16:01:52.148] [http-nio-8099-exec-2] [] - [SecondInterceptor.preHandle:18] [SecondInterceptor preHandle]
  5. [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]]
  6. [INFO 2024-07-27 16:01:52.149] [http-nio-8099-exec-2] [cdc644d0-afdf-4283-bf52-fc5fdd217746] - [TestController.testController:57] [main process]
  7. [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]

原文链接:https://www.cnblogs.com/wenbochang/p/18327158

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号