Spring MVC 多个拦截器的执行顺序
Spring MVC支持配置多个拦截器,它们的执行顺序遵循特定规则,理解这些规则对正确设计拦截链至关重要。
注册顺序决定执行顺序
Java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 按注册顺序配置拦截器
registry.addInterceptor(interceptorA)
.addPathPatterns("/**");
registry.addInterceptor(interceptorB)
.addPathPatterns("/**");
registry.addInterceptor(interceptorC)
.addPathPatterns("/**");
}
}
执行顺序规则
Java
请求进入
↓
preHandle(A) → preHandle(B) → preHandle(C) 【顺序执行】
↓
Controller处理
↓
postHandle(C) → postHandle(B) → postHandle(A) 【逆序执行】
↓
视图渲染
↓
afterCompletion(C) → afterCompletion(B) → afterCompletion(A) 【逆序执行】
| 方法 | 执行顺序 | 说明 |
|---|---|---|
| preHandle | 顺序执行 | 先注册先执行 |
| postHandle | 逆序执行 | 后注册先执行 |
| afterCompletion | 逆序执行 | 后注册先执行 |
执行流程图解
Java
Interceptor A Interceptor B Interceptor C
↓ ↓ ↓
preHandle(A) ─→ preHandle(B) ─→ preHandle(C)
↓
Controller
↓
postHandle(C) ←─ postHandle(B) ←─ postHandle(A)
↓
View渲染
↓
afterCompletion(C)←─ afterCompletion(B)←─ afterCompletion(A)
↓
响应完成
代码验证示例
Java
@Component
public class InterceptorA implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
log.info("InterceptorA - preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
log.info("InterceptorA - postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
log.info("InterceptorA - afterCompletion");
}
}
@Component
public class InterceptorB implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
log.info("InterceptorB - preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
log.info("InterceptorB - postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
log.info("InterceptorB - afterCompletion");
}
}
执行日志输出:
Java
InterceptorA - preHandle
InterceptorB - preHandle
InterceptorC - preHandle
Controller处理...
InterceptorC - postHandle
InterceptorB - postHandle
InterceptorA - postHandle
InterceptorC - afterCompletion
InterceptorB - afterCompletion
InterceptorA - afterCompletion
preHandle返回false的影响
当某个拦截器的preHandle返回false时,后续拦截器不再执行:
text
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptorA)
.addPathPatterns("/**");
registry.addInterceptor(interceptorB)
.addPathPatterns("/**");
}
如果InterceptorA的preHandle返回false:
text
preHandle(A) → 返回false,请求被拦截
↓
后续拦截器B的preHandle不执行
↓
Controller不执行
↓
所有postHandle不执行
↓
afterCompletion(A)执行(已执行preHandle的拦截器)
↓
InterceptorB的afterCompletion不执行
order()方法控制顺序
text
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptorA)
.addPathPatterns("/**")
.order(3); // order值越大,优先级越低
registry.addInterceptor(interceptorB)
.addPathPatterns("/**")
.order(1); // order值越小,优先级越高
registry.addInterceptor(interceptorC)
.addPathPatterns("/**")
.order(2);
}
使用order后的执行顺序:
text
preHandle: B(order=1) → C(order=2) → A(order=3)
postHandle: A(order=3) → C(order=2) → B(order=1)
afterCompletion: A(order=3) → C(order=2) → B(order=1)
order值越小的拦截器,preHandle越先执行,postHandle和afterCompletion越后执行。
实际应用场景
text
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 1. 性能监控拦截器 - 最先执行(order最小)
registry.addInterceptor(performanceInterceptor())
.addPathPatterns("/**")
.order(1);
// 2. 日志记录拦截器
registry.addInterceptor(logInterceptor())
.addPathPatterns("/**")
.order(2);
// 3. 认证拦截器
registry.addInterceptor(authInterceptor())
.addPathPatterns("/api/**")
.order(3);
// 4. 权限拦截器 - 在认证之后执行
registry.addInterceptor(permissionInterceptor())
.addPathPatterns("/api/**")
.order(4);
}
异常情况下的执行顺序
当Controller抛出异常时:
text
preHandle(A) → preHandle(B) → preHandle(C) 正常执行
↓
Controller抛出异常
↓
postHandle均不执行
↓
afterCompletion(C) → afterCompletion(B) → afterCompletion(A) 正常执行(逆序)
Controller异常时postHandle不执行,但afterCompletion仍会正常执行(逆序)。
要点总结
- preHandle按注册顺序执行(先注册先执行)
- postHandle和afterCompletion逆序执行(后注册先执行)
- preHandle返回false会中断后续拦截器执行
- order()方法可显式控制执行顺序,值越小优先级越高
- Controller异常时postHandle不执行,afterCompletion仍执行
📝 发现内容有误?点击此处直接编辑