一、核心定位差异(架构层面对比)
1.1 过滤器(Filter)—— Servlet规范守卫者
- 所属规范:Java EE标准组件
- 作用位置:Web容器层面(Tomcat/Jetty)
- 拦截范围:所有HTTP请求(包括静态资源)
- 典型场景:
// 示例:字符编码过滤器 public class CharsetFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { req.setCharacterEncoding("UTF-8"); chain.doFilter(req, res); // 必须调用 } }
1.2 拦截器(Interceptor)—— Spring MVC的管家
- 所属框架:Spring MVC特有组件
- 作用位置:DispatcherServlet之后
- 拦截范围:Controller请求(不拦截静态资源)
- 典型场景:
@Component public class AuthInterceptor implements HandlerInterceptor { public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) { // 权限校验逻辑 return true; // 放行请求 } }
二、执行流程全景图(重点!)
2.1 完整请求生命周期
sequenceDiagram
participant Client
participant FilterChain
participant DispatcherServlet
participant Interceptor
participant Controller
Client->>FilterChain: 请求进入
FilterChain->>DispatcherServlet: 预处理完成
DispatcherServlet->>Interceptor: preHandle()
Interceptor->>Controller: 执行业务逻辑
Controller->>Interceptor: postHandle()
Interceptor->>FilterChain: 返回响应
FilterChain->>Client: 最终响应
2.2 关键顺序对比表
| 阶段 | 过滤器执行 | 拦截器执行 |
|---|---|---|
| 静态资源访问 | ✅ | ❌ |
| 进入DispatcherServlet前 | ✅ | ❌ |
| Controller方法执行前 | ❌ | ✅ |
| 视图渲染前 | ❌ | ✅ |
| 响应返回前 | ✅ | ✅ |
三、6大核心区别详解
3.1 依赖注入支持对比
// 过滤器无法直接使用@Autowired
public class BadFilter implements Filter {
@Autowired // 这里会注入失败!
private AuthService authService;
}
// 拦截器支持Spring注入
@Component
public class GoodInterceptor implements HandlerInterceptor {
@Autowired // 正常注入
private AuthService authService;
}
解决方案:
通过FilterRegistrationBean包装过滤器:
@Bean
public FilterRegistrationBean<AuthFilter> authFilter(AuthService service) {
FilterRegistrationBean<AuthFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new AuthFilter(service)); // 手动注入
bean.addUrlPatterns("/*");
return bean;
}
3.2 配置方式对比
过滤器配置:
// 方式1:注解配置(需启动类加@ServletComponentScan)
@WebFilter(urlPatterns = "/*")
public class LogFilter implements Filter {}
// 方式2:JavaConfig显式注册
@Bean
public FilterRegistrationBean<LogFilter> loggingFilter() {
FilterRegistrationBean<LogFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new LogFilter());
bean.setOrder(1); // 控制执行顺序
return bean;
}
拦截器配置:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/login");
}
}
3.3 异常处理差异
| 场景 | 过滤器中的异常 | 拦截器中的异常 |
|---|---|---|
| 能否被@ControllerAdvice捕获 | ❌ | ✅ |
| 处理建议 | 自行try-catch | 可抛给全局处理器 |
四、实战场景选型指南
4.1 必须使用过滤器的场景
- 全局字符编码设置
public class EncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { req.setCharacterEncoding("UTF-8"); res.setContentType("application/json;charset=UTF-8"); chain.doFilter(req, res); } } - 敏感词过滤
public class SensitiveFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) { CustomRequestWrapper wrappedRequest = new CustomRequestWrapper((HttpServletRequest) req); chain.doFilter(wrappedRequest, res); } }
4.2 优先使用拦截器的场景
- 接口权限校验
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) { String token = req.getHeader("Authorization"); if(!authService.validateToken(token)) { res.sendError(401, "Invalid token"); return false; } return true; } - 接口耗时监控
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) { req.setAttribute("startTime", System.currentTimeMillis()); return true; } public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) { long duration = System.currentTimeMillis() - (Long)req.getAttribute("startTime"); log.info("请求 {} 耗时 {}ms", req.getRequestURI(), duration); }
五、高级技巧:实现执行顺序控制
5.1 过滤器顺序控制
@Bean
public FilterRegistrationBean<FilterA> filterA() {
FilterRegistrationBean<FilterA> bean = new FilterRegistrationBean<>();
bean.setFilter(new FilterA());
bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 最高优先级
return bean;
}
@Bean
public FilterRegistrationBean<FilterB> filterB() {
FilterRegistrationBean<FilterB> bean = new FilterRegistrationBean<>();
bean.setFilter(new FilterB());
bean.setOrder(Ordered.LOWEST_PRECEDENCE); // 最低优先级
return bean;
}
5.2 拦截器顺序控制
registry.addInterceptor(new Interceptor1()).order(1);
registry.addInterceptor(new Interceptor2()).order(2);
// 数字越小优先级越高
六、常见问题排查指南
6.1 过滤器不生效怎么办?
- 检查是否添加了
@ServletComponentScan - 确认URL模式是否匹配
- 查看FilterRegistrationBean的配置顺序
6.2 拦截器preHandle返回false的后果
- 后续拦截器不再执行
- Controller方法不会调用
- postHandle方法不会触发
- afterCompletion仍然会执行(仅对已通过preHandle的拦截器)
七、终极对比表(建议收藏)
| 特性 | 过滤器(Filter) | 拦截器(Interceptor) |
|---|---|---|
| 规范依赖 | Servlet API | Spring MVC |
| 作用范围 | 所有请求 | Controller请求 |
| 注入Spring Bean | 需特殊处理 | 直接支持 |
| 执行位置 | DispatcherServlet之前 | Controller方法前后 |
| 异常处理 | 需自行处理 | 可被全局异常处理器捕获 |
| 配置方式 | web.xml或JavaConfig | JavaConfig |
| 访问请求体 | 可修改 | 只能读取 |
| 性能影响 | 更高(更底层) | 较低 |
最佳实践建议:优先使用拦截器处理业务相关逻辑,仅在需要处理底层HTTP协议时使用过滤器。掌握两者的区别后,可以查看Spring Boot的默认过滤器链(如Spring Security过滤器链)加深理解。