一、拦截器(Interceptor) vs 过滤器(Filter)
特性 | 拦截器(Interceptor) | 过滤器(Filter) |
---|---|---|
作用范围 | Spring MVC 框架层面 | Servlet 容器层面 |
依赖框架 | 需 Spring 容器支持 | 原生 Servlet 规范 |
访问对象 | 可访问 HandlerMethod、ModelAndView 等对象 | 仅能访问 ServletRequest/Response |
业务关联 | 可获取 Spring Bean 和业务数据 | 无法直接访问 Spring 上下文 |
触发时机 | 在 Controller 方法前后执行 | 在请求进入 Servlet 前/响应返回后执行 |
异常处理 | 可通过 @ControllerAdvice 统一处理 | 需在 web.xml 配置错误页面 |
二、执行顺序
flowchart TD
A[请求] --> B(Filter#doFilter)
B --> C(Interceptor#preHandle)
C --> D[Controller]
D --> E(Interceptor#postHandle)
E --> F(Interceptor#afterCompletion)
F --> G(Filter#doFilter后续逻辑)
G --> H[响应]
- 过滤器链(FilterChain) 按
web.xml
声明顺序依次执行或者按过滤器名称
- 拦截器链(Interceptor) 按注册顺序执行
preHandle
(先进先出) 逆序执行postHandle
和afterCompletion
(后进先出)
三、案例:定义多个拦截器(完整配置示例)
java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 1. 日志拦截器(最先执行)
registry.addInterceptor(new LogInterceptor())
.addPathPatterns("/**")
.order(1); // 数字越小优先级越高
// 2. 认证拦截器
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/secure/**")
.excludePathPatterns("/secure/public")
.order(2);
// 3. 性能监控拦截器(最后执行)
registry.addInterceptor(new PerformanceInterceptor())
.addPathPatterns("/api/**")
.order(3);
}
}
// 示例拦截器实现
class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("[Log] Request URI: " + request.getRequestURI());
return true;
}
}
class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (request.getSession().getAttribute("user") == null) {
response.setStatus(401);
return false;
}
return true;
}
}
class PerformanceInterceptor implements HandlerInterceptor {
private ThreadLocal<Long> startTime = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
startTime.set(System.currentTimeMillis());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.printf("[Performance] %s took %d ms%n",
request.getRequestURI(),
System.currentTimeMillis() - startTime.get()
);
}
}
3.1 关键配置说明
- 执行顺序控制
order()
方法指定优先级(值越小越先执行) - 路径匹配规则
addPathPatterns()
:设置需拦截的路径(支持 Ant 风格)excludePathPatterns()
:设置排除路径 - 拦截器生命周期
preHandle
:Controller 方法执行前postHandle
:Controller 执行后,视图渲染前afterCompletion
:请求完成后(总会执行)
💡 最佳实践:将公共拦截器(如日志、跨域)设为高优先级,业务拦截器(如权限)设为低优先级。