一、技术定位的本质差异
在Servlet容器架构中,过滤器与拦截器分属不同技术层级,这种差异决定了它们的核心应用场景。过滤器工作在Servlet规范层面,属于Web容器的基础组件,其处理范围覆盖所有HTTP请求,包括静态资源、JSP页面和动态接口。而拦截器则是Spring MVC框架的扩展组件,仅对DispatcherServlet分发的请求生效,天然具备Spring上下文感知能力。
这种层级差异带来两个关键特性:
- 执行顺序:过滤器链遵循”先注册先执行”原则,在请求进入Servlet容器时即开始处理;拦截器则通过HandlerExecutionChain管理,在Controller方法调用前后执行
- 上下文访问:过滤器需通过WebApplicationContextUtils手动获取Spring Bean,而拦截器可直接注入依赖
典型案例:某金融系统曾因在过滤器中直接注入Service层组件,导致NPE异常频发,最终通过WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext()).getBean()方式解决。
二、过滤器(Filter)的深度解析
1. 核心能力矩阵
过滤器擅长处理以下三类任务:
- 全局性处理:如跨域配置、请求/响应编码设置
- 资源级控制:静态资源缓存策略、防盗链处理
- 性能监控:接口耗时统计、QPS限制
@WebFilter(urlPatterns = "/*", filterName = "performanceFilter")public class PerformanceFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {long startTime = System.currentTimeMillis();chain.doFilter(request, response);long duration = System.currentTimeMillis() - startTime;// 实际项目建议使用日志框架System.out.printf("Request processed in %d ms%n", duration);}}
2. 关键注意事项
- 线程安全:过滤器实例默认是单例的,共享变量需考虑并发问题
- 异常处理:未捕获的异常会导致请求中断,需妥善处理
- 资源释放:在destroy()方法中释放缓存等资源
- 配置方式:支持注解式(@WebFilter)和编程式(FilterRegistrationBean)两种方式
三、拦截器(HandlerInterceptor)的实战指南
1. 典型应用场景
拦截器在以下场景具有不可替代性:
- 权限验证:基于Token/JWT的鉴权机制
- 数据预处理:请求参数自动解密、响应数据加密
- 流程控制:熔断降级、限流处理
- 审计日志:记录操作人、操作时间等元数据
public class AuthInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception {String token = request.getHeader("Authorization");if (StringUtils.isBlank(token) || !JwtUtil.verify(token)) {response.sendError(HttpStatus.UNAUTHORIZED.value(), "Invalid token");return false;}// 将用户信息存入请求属性request.setAttribute("currentUser", JwtUtil.parseUser(token));return true;}}
2. 高级配置技巧
通过WebMvcConfigurer实现精细化控制:
@Configurationpublic class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**").excludePathPatterns("/api/public/**","/api/login","/error");}}
四、选型决策树
构建技术选型需考虑以下维度:
-
处理范围:
- 需要处理静态资源 → 选择过滤器
- 仅需处理动态请求 → 优先考虑拦截器
-
上下文需求:
- 需要访问Spring Bean → 拦截器或过滤器+ApplicationContext工具类
- 仅需HTTP基础信息 → 过滤器更轻量
-
执行顺序要求:
- 需要最早执行(如日志记录)→ 过滤器
- 需要在Controller前后执行(如参数校验)→ 拦截器
-
性能敏感度:
- 高并发场景 → 过滤器需注意同步问题,拦截器更易优化
五、混合使用最佳实践
在复杂系统中,常采用”过滤器+拦截器”的组合模式:
-
安全链:
- 过滤器层:IP白名单、基础参数校验
- 拦截器层:权限验证、数据脱敏
-
监控链:
- 过滤器层:记录原始请求信息
- 拦截器层:记录业务处理耗时
-
异常处理链:
- 过滤器层:捕获Servlet异常
- 拦截器层:捕获业务异常
六、常见误区与解决方案
-
过滤器中直接使用@Autowired:
- 错误示范:
@Autowired private UserService userService; - 正确做法:通过FilterConfig获取ApplicationContext
- 错误示范:
-
拦截器preHandle返回false后的处理:
- 需确保调用response.sendError()或写入响应体
- 避免继续执行postHandle和afterCompletion
-
异步请求处理:
- 过滤器需实现AsyncListener接口
- 拦截器需配置
@EnableAsync和异步任务超时设置
七、性能优化建议
-
过滤器链优化:
- 将高频使用的过滤器前置
- 避免在过滤器中执行耗时操作
-
拦截器缓存:
- 对静态权限数据使用本地缓存
- 合理设置缓存失效策略
-
监控集成:
- 集成监控系统记录处理耗时
- 设置合理的告警阈值
在微服务架构盛行的今天,理解请求处理链的底层机制尤为重要。无论是单体应用还是分布式系统,正确的拦截机制选型都能显著提升系统的安全性、可维护性和性能表现。开发者应根据具体业务场景,结合本文提供的决策模型和最佳实践,构建高效稳定的请求处理管道。