SpringBoot中WebMvcConfigurer注册多个拦截器(addInterceptors)时的顺序问题(二)

在Spring MVC的拦截器(Interceptor)中,preHandlepostHandleafterCompletion 这三个方法的执行顺序与整个请求-响应流程密切相关。以下是它们的详细执行顺序和触发时机:


1. 完整执行顺序流程图

复制代码
客户端请求 → 
    Interceptor1.preHandle → 
        Interceptor2.preHandle → 
            Controller方法执行 → 
                Interceptor2.postHandle → 
                    Interceptor1.postHandle → 
                        视图渲染(如果有) → 
                            Interceptor2.afterCompletion → 
                                Interceptor1.afterCompletion → 
                                    响应返回客户端

2. 各方法的具体作用与顺序

(1) preHandle(请求到达Controller前)
  • 执行顺序 :按拦截器的order从小到大 依次执行(order值越小优先级越高)。

  • 返回值

    • 返回 true:继续调用后续拦截器或Controller。

    • 返回 false:中断请求,直接返回(后续拦截器、Controller、postHandleafterCompletion均不会执行)。

  • 典型用途:权限校验、参数预处理、日志记录。

(2) postHandle(Controller执行后,视图渲染前)
  • 执行顺序 :按拦截器的order从大到小 依次执行(与preHandle相反)。

  • 触发时机:Controller方法执行完毕,但尚未进行视图渲染(如Thymeleaf、Freemarker等)。

  • 注意 :如果Controller中发生异常,此方法不会被执行

  • 典型用途:修改ModelAndView、记录响应数据。

(3) afterCompletion(请求完成后,包括视图渲染)
  • 执行顺序 :按拦截器的order从大到小 依次执行(与postHandle相同)。

  • 触发时机:整个请求处理完成(包括视图渲染),无论是否有异常都会执行。

  • 典型用途:资源清理、性能监控、异常日志记录。


3. 关键注意事项

  1. 拦截器链的执行

    • 若某个拦截器的preHandle返回false,后续拦截器的preHandle、Controller、postHandleafterCompletion均不会执行。

    • 只有所有preHandle都返回true时,Controller才会执行。

  2. 异常处理的影响

    • 如果Controller抛出异常:

      • postHandle不会执行

      • afterCompletion仍会执行 (可通过ex参数获取异常对象)。

  3. @ControllerAdvice的差异

    • 拦截器的afterCompletion在视图渲染后触发,而@ControllerAdvice@ExceptionHandler在异常发生时立即处理(早于afterCompletion)。

4. 示例场景

假设有两个拦截器:

  • AuthInterceptororder = 1

  • LoggingInterceptororder = 2

正常流程:
复制代码
1. AuthInterceptor.preHandle()     (order=1, 最先执行)
2. LoggingInterceptor.preHandle() (order=2)
3. Controller方法执行
4. LoggingInterceptor.postHandle() (order=2, 逆序)
5. AuthInterceptor.postHandle()   (order=1)
6. 视图渲染
7. LoggingInterceptor.afterCompletion() (order=2, 逆序)
8. AuthInterceptor.afterCompletion()   (order=1)
中断流程(如权限校验失败):
复制代码
1. AuthInterceptor.preHandle() 返回false
   // 后续所有方法均不执行,直接返回客户端
异常流程(Controller抛出异常):
复制代码
1. AuthInterceptor.preHandle()     (order=1)
2. LoggingInterceptor.preHandle()  (order=2)
3. Controller抛出异常
4. LoggingInterceptor.afterCompletion() (携带异常对象)
5. AuthInterceptor.afterCompletion()   (携带异常对象)
   // postHandle 不会执行

5. 总结

  • preHandle:是拦截器的"入口",决定请求是否继续。

  • postHandle:可修改响应数据,但无法处理异常。

  • afterCompletion:最适合做资源清理和最终日志记录,无论成功失败都会执行。

通过合理组合这三个方法,可以实现灵活的请求处理逻辑(如权限链、日志追踪、性能监控等)。

相关推荐
Goldn.21 分钟前
Java核心技术栈全景解析:从Web开发到AI融合
java· spring boot· 微服务· ai· jvm· maven· hibernate
oden30 分钟前
AI服务商切换太麻烦?一个AI Gateway搞定监控、缓存和故障转移(成本降40%)
后端·openai·api
ะัี潪ิื31 分钟前
springboot加载本地application.yml和加载Consul中的application.yml配置反序列化LocalDate类型差异
spring boot·consul·java-consul
李慕婉学姐1 小时前
【开题答辩过程】以《基于Android的出租车运行监测系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·后端·vue
m0_740043732 小时前
SpringBoot05-配置文件-热加载/日志框架slf4j/接口文档工具Swagger/Knife4j
java·spring boot·后端·log4j
编织幻境的妖2 小时前
SQL查询连续登录用户方法详解
java·数据库·sql
未若君雅裁2 小时前
JVM面试篇总结
java·jvm·面试
kk哥88992 小时前
C++ 对象 核心介绍
java·jvm·c++
招风的黑耳3 小时前
我用SpringBoot撸了一个智慧水务监控平台
java·spring boot·后端
xunyan62343 小时前
面向对象(下)-接口的理解
java·开发语言