Skip to content

在 Spring 中,拦截器和过滤器有什么区别? ​

  • 标签:Spring、Java

🏛 业务架构师 ​

拦截器(HandlerInterceptor)和过滤器(Filter)的区别,核心是所属体系与作用时机:

  • Filter 是 Servlet 规范的组件:在请求进入 Spring MVC 之前、响应离开之后工作(filter chain 最外层),能拿到原始请求响应,但感知不到 Handler 是谁;
  • Interceptor 是 Spring MVC 的组件:在 DispatcherServlet 之后、Handler 执行前后介入,能拿到 handler 信息(方法、注解),且可使用 Spring 容器能力。

业务架构师视角,我按治理职责分层来分配它们:

  1. Filter 层放"协议级/横切基础设施":全链路最外层的字符编码、CORS、全局 traceId 注入、请求体日志(审计需要原始报文时)、防 XSS 清洗——这些不关心业务路由,越早执行越好;
  2. Interceptor 层放"业务路由感知"的治理:鉴权(知道要调哪个接口、能读方法上的权限注解)、用户/租户上下文注入、接口级访问日志与耗时、灰度标记——需要"这是哪个业务接口"的信息才能做对;
  3. 顺序上 Filter 先于 Interceptor 执行。一个典型的完整链:Filter(traceId/CORS) → Interceptor(鉴权/上下文) → Controller。

实践提醒:Spring Boot 里自定义 Filter 有两种注册方式(@WebFilter+@ServletComponentScan 或 FilterRegistrationBean),用后者才能精确控制顺序和 URL 匹配——顺序错误的鉴权过滤器是真实安全事故来源。

🏗 系统架构师 ​

六个维度对比:

维度FilterInterceptor
规范Servlet 规范Spring MVC
范围所有请求(含静态资源)只到 Handler 层
上下文Servlet 体系天然是容器 Bean
粒度请求级拿得到 HandlerMethod 元数据(方法、注解)
时机最外层,先于 DispatcherServletFilter 之后、Controller 之前
用途编码、CORS、安全头、XSS认证鉴权、traceId、审计、灰度

我的分层放置原则:

  • 与协议/容器相关放 Filter(它不该理解 Spring);
  • 与业务路由相关(要读注解、区分接口)放 Interceptor;
  • 跨服务统一的横切(限流、熔断、请求清洗)上收网关,应用内只留本地校验。

执行时序:Filter 链 → DispatcherServlet → Interceptor preHandle → Controller → postHandle → afterCompletion → Filter 返回。画得出这条时序,MDC 泄漏、清理乱序这类问题才排得动。

💻 全栈开发专家 ​

同是横切手段,层次和出身不同:

维度Filter 过滤器Interceptor 拦截器
规范Servlet 规范Spring MVC 机制
位置最外层,DispatcherServlet 之前DispatcherServlet 内、handler 前后
能拿到什么原始 request/responsehandler 方法元数据(HandlerMethod、注解)
典型场景编码、CORS、XSS 过滤、请求体包装登录态、权限、接口审计
异常抛错到不了 @ControllerAdvice能被全局异常处理器接住
Bean 注入DelegatingFilterProxy 或手动天然是 Spring Bean

执行顺序:Filter chain 前 → Interceptor preHandle → Controller → postHandle → afterCompletion → Filter chain 后。

选型口诀:协议/容器层面的事给 Filter,业务语义的事给 Interceptor。实例对比:全局访问日志要重复读 body,必须 Filter + ContentCachingRequestWrapper;"只对带 @RequirePermission 注解的接口鉴权"必须 Interceptor(Filter 看不到方法注解)。Spring Security 本质是一组 Filter(FilterChainProxy),所以在 MVC 拦截器之前生效——这条最能体现层次理解。