Spring MVC 拦截器配置类详解(按调用顺序)
Spring MVC 提供了多种拦截器配置类和接口,以下是按调用顺序排列的详细说明:
1. HandlerInterceptor 接口
调用顺序:最先执行
功能:
核心拦截器接口,定义了三个拦截点:
- preHandle - 处理器执行前
- postHandle - 处理器执行后,视图渲染前
- afterCompletion - 请求完成后
使用示例:
public class LoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
log.info("请求开始: " + request.getRequestURI());
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) {
log.info("请求处理完成: " + request.getRequestURI());
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
log.info("请求结束: " + request.getRequestURI());
}
}
2. HandlerInterceptorAdapter(已废弃)
调用顺序:同 HandlerInterceptor
功能:
HandlerInterceptor 的适配器类(Spring 5.3+ 已废弃)
提供空实现,只需覆盖需要的方法
替代方案:
// 直接实现 HandlerInterceptor 接口
public class MyInterceptor implements HandlerInterceptor {
// 使用 default 方法可以不实现所有方法
}
3. AsyncHandlerInterceptor 接口
调用顺序:在普通 HandlerInterceptor 之后
功能:
扩展 HandlerInterceptor,增加异步请求处理支持
新增方法:
afterConcurrentHandlingStarted - 当处理程序开始异步执行时调用
使用场景:
public class AsyncInterceptor implements AsyncHandlerInterceptor {
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
// 异步请求开始时调用
log.info("异步请求开始: " + request.getRequestURI());
}
}
4. WebRequestInterceptor 接口
调用顺序:在 HandlerInterceptor 之后
功能:
提供更高级的 Web 请求抽象
不同于 HandlerInterceptor,它不依赖 Servlet API
方法:
preHandle(WebRequest request)
postHandle(WebRequest request, ModelMap model)
afterCompletion(WebRequest request, Exception ex)
使用示例:
public class WebRequestLogInterceptor implements WebRequestInterceptor {
@Override
public void preHandle(WebRequest request) throws Exception {
log.info("WebRequest预处理: " + request.getContextPath());
}
@Override
public void postHandle(WebRequest request, ModelMap model) throws Exception {
if (model != null) {
log.info("模型数据: " + model);
}
}
@Override
public void afterCompletion(WebRequest request, Exception ex) throws Exception {
if (ex != null) {
log.error("请求异常", ex);
}
}
}
5. MappedInterceptor 类
调用顺序:最后执行(但内部拦截器按注册顺序)
功能:
包装拦截器并添加路径匹配功能
可以指定包含路径和排除路径
配置方式:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoggingInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/public/**");
// 等同于
MappedInterceptor mappedInterceptor = new MappedInterceptor(
new String[] {"/api/**"},
new String[] {"/api/public/**"},
new LoggingInterceptor());
registry.addInterceptor(mappedInterceptor);
}
}
6. InterceptorRegistry 类
调用顺序:管理所有拦截器的执行顺序
功能:
用于注册和排序拦截器
可以通过 order() 方法指定顺序
配置示例:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 按添加顺序执行,除非指定order
registry.addInterceptor(new SecurityInterceptor()).order(1);
registry.addInterceptor(new LoggingInterceptor()).order(2);
registry.addInterceptor(new PerformanceInterceptor()).order(3);
}
}
7. Servlet API 原生过滤器 (Filter)
调用顺序:在 Spring 拦截器之前执行
功能:
虽然不属于 Spring MVC 拦截器,但常与拦截器配合使用
更底层的 Servlet 规范实现
与拦截器的区别:
特性 | Filter | Spring 拦截器 |
---|---|---|
规范 | Servlet规范 | Spring 特有 |
执行时机 | 更早(在DispatcherServlet之前) | 在DispatcherServlet之后 |
访问对象 | ServletRequest/Response | HttpServletRequest/Response |
依赖 | 不依赖Spring | 需要Spring环境 |
配置示例:
@Bean
public FilterRegistrationBean<MyFilter> myFilter() {
FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new MyFilter());
registration.addUrlPatterns("/*");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE); // 最高优先级
return registration;
}
完整执行顺序总结
- Servlet Filter (如果有多个,按order顺序)
- HandlerInterceptor.preHandle (按注册顺序)
- Controller方法执行
- HandlerInterceptor.postHandle (按注册逆序)
- 视图渲染
- HandlerInterceptor.afterCompletion (按注册逆序)
- 异步请求特有:AsyncHandlerInterceptor.afterConcurrentHandlingStarted
最佳实践建议
安全相关 :使用Filter或高order值的拦截器
日志记录:使用低order值的拦截器
性能监控:使用preHandle和afterCompletion计算耗时
API版本控制:使用preHandle处理版本头
参数预处理:使用WebRequestInterceptor
通过合理组合这些拦截器组件,可以实现强大的横切关注点处理能力,同时保持业务代码的整洁性。