【Filter / Interceptor】过滤器(Filter)与拦截器(Interceptor)全方位对比解析(附底层原理 + 核心对比表)

0 阅读17分钟

过滤器(Filter)与拦截器(Interceptor)系统性知识体系

本文从核心定位、底层原理、API规范、执行流程、核心对比、场景选型、最佳实践、避坑指南8个维度,构建完整的知识体系,明确两者的边界、能力与适用场景。


一、核心定位与体系总览

过滤器与拦截器是Java Web开发中基于责任链设计模式实现的请求处理组件,核心差异在于所属层级与依赖环境,是请求全链路处理中不同阶段的流量管控入口:

组件规范归属执行层级核心定位
过滤器FilterJava Servlet/Jakarta EE 规范Web容器(Tomcat等)层级容器级请求拦截器,处理所有进入容器的HTTP请求
拦截器InterceptorSpring Framework 规范Spring MVC 上下文层级框架级请求拦截器,精细化处理Spring MVC分发的业务请求

【重点】核心对比表

对比维度过滤器(Filter)拦截器(Interceptor)
规范归属Java Servlet/Jakarta EE 官方规范Spring Framework 框架规范
执行层级Web容器(Tomcat等)层级Spring MVC 上下文层级
依赖环境依赖Web容器,不依赖Spring框架依赖Spring容器,不强制依赖Web容器
触发时机请求进入容器后、Servlet执行前请求进入DispatcherServlet后、Controller执行前
拦截范围所有进入容器的HTTP请求(静态资源、Servlet、接口等)仅DispatcherServlet分发的请求(默认仅Controller接口)
Bean访问能力无法直接注入Spring Bean,需额外配置可自由注入Spring容器中所有Bean
上下文信息仅能获取请求/响应基础信息可获取Controller方法、注解、ModelAndView等全量MVC上下文
执行顺序优先于拦截器执行,Order值越小优先级越高晚于过滤器执行,注册顺序/Order值越小优先级越高
执行控制仅能通过chain.doFilter()控制链路可通过preHandle返回值直接终止请求,控制粒度更细
异常处理无法被Spring全局异常处理器捕获可被Spring全局异常处理器统一处理
适用粒度容器级、全请求通用的无状态处理业务级、细粒度、依赖Spring上下文的处理

二、过滤器(Filter)

2.1 核心定义与底层原理

Filter是Servlet规范定义的原生组件,运行在Web容器中,在请求进入Servlet之前、响应返回客户端之前执行,是容器层面的请求第一道/最后一道关卡。

  • 核心设计模式:责任链模式,通过FilterChain串联多个Filter,形成链式执行
  • 核心特性:不依赖Spring框架,脱离Web容器无法运行;可拦截所有映射到容器的请求(静态资源、Servlet、JSP、Spring接口等)

2.2 核心API与生命周期

2.2.1 核心接口
  • Java EE(Spring Boot 2.x及以下):javax.servlet.Filter
  • Jakarta EE(Spring Boot 3.x及以上):jakarta.servlet.Filter(包名变更,旧代码需适配)
2.2.2 生命周期方法
方法执行时机核心作用执行次数
init(FilterConfig filterConfig)容器启动时,Filter实例化后执行初始化Filter配置、加载资源容器生命周期内仅1次
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)每次请求匹配到Filter时执行核心请求/响应处理逻辑,通过chain.doFilter()调用下一个Filter/目标Servlet每次匹配请求执行1次
destroy()容器关闭时,Filter销毁前执行资源释放、清理容器生命周期内仅1次
2.2.3 关键扩展基类

OncePerRequestFilter:Spring提供的Filter抽象基类,解决原生Filter在请求转发、包含场景下多次执行的问题,Spring内置Filter(编码、跨域等)均继承该类。

2.3 主流配置方式

  1. 注解配置@WebFilter 标注Filter类,配合@ServletComponentScan 扫描注册
    • 缺点:无法精准控制执行顺序,默认按类名字典序排序
  2. Spring Boot 注册Bean配置(推荐):通过FilterRegistrationBean 注册,可精准控制顺序、拦截路径、启动顺序
  3. 传统web.xml配置:Servlet原生配置方式,现已极少使用

2.4 能力边界与典型场景

能力边界
  • 可操作对象:仅ServletRequest/ServletResponse,无法直接访问Spring上下文Bean、Spring MVC上下文信息
  • 拦截范围:所有进入Web容器的请求,无法拦截非Web请求、方法级调用
  • 异常处理:Filter中抛出的异常无法被Spring全局异常处理器(@RestControllerAdvice)捕获
典型使用场景
  • 全链路请求编码设置(CharacterEncodingFilter
  • CORS跨域资源共享处理
  • XSS/CSRF攻击防护、请求参数脱敏
  • 全链路日志追踪(TraceId透传)
  • 全局黑白名单、接口限流
  • 静态资源缓存控制、响应压缩

三、拦截器(Interceptor)

3.1 核心定义与底层原理

Interceptor是Spring MVC原生组件,基于Spring AOP思想实现,运行在DispatcherServlet请求分发流程中,是Spring上下文层面的业务请求管控组件。

  • 核心设计模式:责任链模式,通过HandlerExecutionChain 串联多个Interceptor,形成链式执行
  • 核心特性:依赖Spring容器,可访问Spring上下文中所有Bean;可获取Spring MVC全链路上下文信息,支持细粒度的请求管控

3.2 核心API与生命周期

3.2.1 核心接口

org.springframework.web.servlet.HandlerInterceptor,Spring 5.3之后废弃HandlerInterceptorAdapter适配类,直接通过接口default方法实现自定义逻辑。

3.2.2 核心生命周期方法
方法执行时机核心作用执行规则
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)Controller方法执行前前置校验(鉴权、限流等),返回true放行,false终止请求按注册顺序正序执行;仅返回true才会触发后续方法
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)Controller方法执行后,视图渲染前后置处理,可修改ModelAndView、统一追加响应参数按注册顺序倒序执行
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)整个请求处理完成(视图渲染完毕)后资源清理、异常收尾处理按注册顺序倒序执行;仅对应preHandle返回true的拦截器会执行
3.2.3 扩展接口

AsyncHandlerInterceptor:继承HandlerInterceptor,新增afterConcurrentHandlingStarted方法,专门处理Spring异步请求的拦截场景。

3.3 主流配置方式

  1. Spring Boot Java配置(推荐):实现WebMvcConfigurer接口,重写addInterceptors方法,注册拦截器、配置拦截/排除路径、控制执行顺序
  2. Spring MVC XML配置:通过<mvc:interceptors>标签配置,现已极少使用

3.4 能力边界与典型场景

能力边界
  • 可操作对象:HttpServletRequest/HttpServletResponseHandlerMethod(Controller方法元信息)、ModelAndView、Spring容器所有Bean
  • 拦截范围:仅DispatcherServlet分发的请求(默认仅Controller接口,静态资源需额外配置映射才能拦截),无法拦截非Spring管理的类、非Web请求
  • 异常处理:可被Spring全局异常处理器捕获,支持与Spring异常体系无缝集成
典型使用场景
  • 登录认证、接口权限校验(基于Token/角色的细粒度鉴权)
  • 接口访问日志记录(入参、出参、执行耗时统计)
  • 接口幂等性校验、重复提交拦截
  • 国际化、主题切换、用户上下文透传
  • Controller层统一参数预处理/响应后处理
  • 业务级接口限流、灰度发布控制

四、全链路执行时序与流程详解

5.1 完整请求-响应全流程

客户端发送HTTP请求
    ↓
Web服务器(Tomcat)接收请求,进入Servlet容器
    ↓
【过滤器链 正序执行】所有FilterdoFilter() 前置逻辑
    ↓
过滤器链末端,进入DispatcherServlet
    ↓
DispatcherServlet通过HandlerMapping匹配目标Controller
    ↓
【拦截器链 正序执行】所有Interceptor的preHandle()方法
    ↓
所有preHandle()均返回true,执行Controller目标方法
    ↓
Controller执行完毕,返回ModelAndView
    ↓
【拦截器链 倒序执行】所有Interceptor的postHandle()方法
    ↓
DispatcherServlet执行视图渲染
    ↓
【拦截器链 倒序执行】所有Interceptor的afterCompletion()方法
    ↓
【过滤器链 倒序执行】所有FilterdoFilter() 后置逻辑
    ↓
Web容器将响应结果返回客户端

5.2 多组件执行顺序示例

假设存在2个Filter(Filter1 Order=1、Filter2 Order=2),2个Interceptor(Interceptor1 Order=1、Interceptor2 Order=2),最终执行顺序为:

Filter1 前置逻辑 → Filter2 前置逻辑
→ Interceptor1.preHandle() → Interceptor2.preHandle()
→ Controller方法执行
→ Interceptor2.postHandle() → Interceptor1.postHandle()
→ 视图渲染
→ Interceptor2.afterCompletion() → Interceptor1.afterCompletion()
→ Filter2 后置逻辑 → Filter1 后置逻辑

五、场景选型与最佳实践

6.1 核心选型原则

  1. 容器级、全请求通用的无业务逻辑处理,优先用Filter 例:编码设置、跨域处理、XSS防护、全链路TraceId透传
  2. 业务级、依赖Spring Bean、细粒度的Controller层处理,优先用Interceptor 例:登录鉴权、权限校验、业务日志、幂等性控制
  3. Service/Dao层的方法级管控,用Spring AOP,而非Interceptor/Filter

6.2 过滤器最佳实践

  1. 优先使用FilterRegistrationBean注册,精准控制Order、拦截路径,避免@WebFilter的顺序问题
  2. 继承OncePerRequestFilter实现自定义Filter,避免一次请求多次执行
  3. 读取请求体时,必须使用ContentCachingRequestWrapper包装Request,避免流只能读取一次导致Controller无法获取参数
  4. Filter中仅做通用、无状态的处理,禁止写入业务逻辑,禁止耗时操作
  5. Filter中异常需自行处理,或转发到错误页面,无法依赖Spring全局异常处理器
  6. Spring Boot 3.x+必须使用jakarta.servlet包下的Filter接口,避免导包错误导致不生效

6.3 拦截器最佳实践

  1. 自定义拦截器必须注册为Spring Bean(配置类中用@Bean声明),禁止在addInterceptors中直接new对象,否则会导致Bean注入为null
  2. preHandle()返回false时,必须手动写入响应数据,避免客户端收到空白响应
  3. 禁止在postHandle()中修改响应体,此时响应流可能已提交,会抛出IllegalStateException
  4. afterCompletion()中必须清理ThreadLocal、临时资源,避免线程复用导致的数据错乱与内存泄漏
  5. 异步请求必须实现AsyncHandlerInterceptor接口,避免拦截逻辑失效
  6. 配置拦截路径时,必须排除静态资源、健康检查、错误页面等非业务请求路径

六、进阶知识与常见坑点

7.1 进阶知识边界

  1. Filter、Interceptor、Spring AOP的粒度差异
    • Filter:容器级,粒度最粗,管控所有进入容器的请求
    • Interceptor:MVC框架级,粒度中等,管控Controller层请求
    • AOP:方法级,粒度最细,管控任意Spring Bean的方法(Service、Dao等)
  2. 拦截器的扩展能力 可通过handler参数获取HandlerMethod对象,解析Controller方法上的自定义注解,实现基于注解的精细化管控(例:仅标注@LoginRequired的接口执行鉴权)
  3. 过滤器的全局生效规则 Filter的默认拦截路径为/*,可匹配所有请求;而Interceptor默认仅匹配/路径下的DispatcherServlet分发请求,需手动配置通配符

7.2 高频坑点避坑指南

Filter 高频坑
  1. ❌ 导包错误:Spring Boot 3.x+使用javax.servlet.Filter,导致Filter不生效
  2. ❌ 读取请求流后未包装Request,导致Controller参数为空
  3. ❌ 用@WebFilter注册,无法控制执行顺序,导致逻辑异常
  4. ❌ Filter中抛出异常,未做处理,导致服务返回500错误,无法被全局异常捕获
Interceptor 高频坑
  1. ❌ 直接new拦截器对象注册,导致@Autowired注入的Bean为null
  2. ❌ preHandle返回false,未设置响应,导致客户端空白页
  3. ❌ ThreadLocal在afterCompletion中未清理,导致数据泄露
  4. ❌ 静态资源被拦截,导致页面样式、图片加载失败
  5. ❌ 异步请求使用普通HandlerInterceptor,导致拦截逻辑不完整
  6. ❌ postHandle中修改响应体,导致流提交异常

附1:底层原理

以下从核心设计模式、容器/框架处理流程、关键组件实现、生命周期管理等维度,深入解析两者的底层工作机制。

底层原理的核心差异总结

维度过滤器(Filter)拦截器(Interceptor)
管理主体Web 容器(Tomcat 等)Spring 容器
链实现载体ApplicationFilterChain(数组+索引)HandlerExecutionChain(List+索引)
依赖注入默认不支持,需手动获取 Spring 上下文原生支持,直接注入 Spring Bean
设计模式纯责任链模式责任链模式 + AOP 思想
执行嵌入点Web 容器请求管道Spring MVC DispatcherServlet 核心流程

一、过滤器(Filter)底层原理

1. 核心设计模式:责任链模式(Chain of Responsibility)

Filter 是 Servlet 规范对责任链模式的原生实现:

  • 角色划分
    • Filter:抽象处理者(每个 Filter 是一个具体处理节点)
    • FilterChain:责任链管理器(串联所有 Filter,控制链路流转)
  • 流转逻辑:请求依次经过链上的每个 Filter,通过 chain.doFilter() 显式调用下一个节点,最终到达目标 Servlet;响应则沿原链路反向返回。

2. Servlet 容器的请求处理流程

以 Tomcat 为例,Filter 的底层执行嵌入在容器的请求管道中:

客户端请求 → Tomcat Connector(接收连接) → Engine → Host → Context
→ FilterChain(依次执行所有 Filter 的 doFilter 前置逻辑)
→ 目标 Servlet(处理业务)
→ FilterChain(依次执行所有 Filter 的 doFilter 后置逻辑)
→ 响应返回客户端
  • 核心机制:Filter 是容器级的“请求拦截器”,在 Servlet 执行前后插入逻辑,完全由 Web 容器(而非 Spring)管理生命周期。

3. 关键组件:FilterChain 的实现机制

Tomcat 中的 FilterChain 实现类为 ApplicationFilterChain,底层是一个数组 + 索引的结构:

  • 内部维护 Filter[] filters 数组存储所有匹配的 Filter
  • 维护 int pos 索引记录当前执行到的 Filter 位置
  • 调用 chain.doFilter() 时:
    1. pos < filters.length,则 pos++,调用下一个 Filter 的 doFilter()
    2. pos == filters.length,则调用目标 Servlet 的 service() 方法

4. 生命周期的底层管理

Filter 的生命周期完全由 Web 容器控制:

  • 实例化:容器启动时,扫描 web.xml@WebFilter 或 Spring Boot 的 FilterRegistrationBean,通过反射创建 Filter 实例(单例模式,全局唯一)
  • 初始化:调用 init(FilterConfig config),传入容器封装的配置信息(初始化参数、ServletContext 等)
  • 销毁:容器关闭时,调用 destroy() 释放资源,随后 Filter 实例被 GC 回收

5. OncePerRequestFilter 的避坑原理

Spring 提供的 OncePerRequestFilter 解决了原生 Filter 重复执行的问题:

  • 底层通过请求属性标记实现:在第一次执行时,向 HttpServletRequest 中设置一个属性(如 filterName.FILTERED
  • 后续执行前检查该属性是否存在,若存在则跳过核心逻辑,确保一次请求仅执行一次 doFilterInternal()(用户自定义的核心方法)

二、拦截器(Interceptor)底层原理

1. 核心设计模式:责任链模式 + Spring AOP 思想

Interceptor 是 Spring MVC 基于责任链模式的实现,同时融合了 AOP 的“环绕通知”思想:

  • 责任链模式:通过 HandlerExecutionChain 串联多个 Interceptor,按顺序执行前置/后置逻辑
  • AOP 思想:在 Controller 方法执行前后插入横切逻辑(类似 AOP 的 @Before@AfterReturning@After),但不依赖动态代理,而是嵌入在 Spring MVC 的请求分发流程中

2. Spring MVC 的请求分发全流程

Interceptor 的底层执行嵌入在 DispatcherServlet 的核心逻辑中:

客户端请求 → DispatcherServlet 接收
→ HandlerMapping 匹配目标 Handler(Controller 方法)
→ 组装 HandlerExecutionChain(包含 Handler + 所有匹配的 Interceptor)
→ 依次执行所有 Interceptor 的 preHandle()(正序)
→ 若所有 preHandle() 返回 true,调用 HandlerAdapter 执行 Controller 方法
→ 依次执行所有 Interceptor 的 postHandle()(倒序)
→ 视图渲染(若需要)
→ 依次执行所有 Interceptor 的 afterCompletion()(倒序)
→ 响应返回客户端
  • 核心机制:Interceptor 是 Spring MVC 框架级的“请求拦截器”,完全由 Spring 容器管理,可访问 Spring 上下文中的所有 Bean。

3. 关键组件:HandlerExecutionChain 的组装与执行

HandlerExecutionChain 是 Interceptor 链的核心载体,底层结构与执行逻辑如下:

  • 内部结构
    • Object handler:目标 Controller 方法(封装为 HandlerMethod 对象)
    • List<HandlerInterceptor> interceptors:匹配到的 Interceptor 列表
    • int interceptorIndex:记录当前执行到的 Interceptor 索引(用于倒序执行后置方法)
  • 执行逻辑
    1. preHandle 正序执行:遍历 interceptors,依次调用 preHandle(),若返回 false,则直接倒序调用已执行 Interceptor 的 afterCompletion(),终止请求
    2. postHandle 倒序执行:Controller 执行完后,从 interceptorIndex 开始倒序调用 postHandle()
    3. afterCompletion 倒序执行:视图渲染完后,从 interceptorIndex 开始倒序调用 afterCompletion()

4. 与 Spring 容器的集成(Bean 注入的原理)

Interceptor 能直接注入 Spring Bean 的底层原因:

  • Interceptor 本身是 Spring 容器管理的 Bean(通过 @Component 注册或配置类中 @Bean 声明)
  • Spring 在组装 HandlerExecutionChain 时,直接从容器中获取 Interceptor 实例,因此支持依赖注入(@Autowired、构造器注入等)
  • 对比:Filter 由 Web 容器实例化,默认无法访问 Spring Bean,需通过 WebApplicationContextUtils 手动获取容器上下文

5. 与 Spring AOP 的本质区别

虽然 Interceptor 融合了 AOP 思想,但与纯 Spring AOP 有本质不同:

维度InterceptorSpring AOP
实现方式嵌入 Spring MVC 请求分发流程,基于责任链基于动态代理(JDK 动态代理/CGLIB)
拦截范围仅 Controller 层请求任意 Spring Bean 的方法(Service、Dao 等)
上下文信息可获取 HttpServletRequest/HttpServletResponseHandlerMethod仅能获取方法参数、返回值等方法级信息
执行时机仅在 Web 请求流程中生效任意方法调用时生效(包括非 Web 场景)

附2:核心区别

一句话总结

Filter 是「Web 容器的门卫」,管所有进容器的请求;Interceptor 是「Spring MVC 的管家」,专管业务请求的精细化管控。

两者均是基于责任链模式的请求处理组件,但在所属层级、依赖环境、能力边界上有本质差异,核心区别如下:


1. 规范归属与管理主体不同

  • 过滤器(Filter):属于 Java Servlet/Jakarta EE 官方规范,由 Web 容器(Tomcat、Jetty 等) 直接管理生命周期,脱离 Web 容器无法运行。
  • 拦截器(Interceptor):属于 Spring Framework 框架规范,由 Spring 容器 管理生命周期,依赖 Spring 环境才能生效。

2. 执行层级与触发时机不同

  • 过滤器:执行在 Web 容器层级,触发时机为「请求进入容器后、Servlet 执行前」,是请求的「第一道关卡」。
  • 拦截器:执行在 Spring MVC 上下文层级,触发时机为「请求进入 DispatcherServlet 后、Controller 执行前」,嵌入在 Spring MVC 的请求分发流程中。

3. 依赖注入与上下文能力不同

  • 过滤器:默认无法直接注入 Spring Bean(需手动获取 Spring 上下文),仅能获取 ServletRequest/ServletResponse 等基础请求/响应信息。
  • 拦截器:原生支持依赖注入(可自由注入 Spring 容器中的任意 Bean),还能获取 HandlerMethod(Controller 方法元信息)、ModelAndView 等全量 Spring MVC 上下文。

4. 拦截范围与控制粒度不同

  • 过滤器:拦截所有进入 Web 容器的 HTTP 请求(包括静态资源、Servlet、JSP、Spring 接口等),控制粒度较粗。
  • 拦截器:默认仅拦截 DispatcherServlet 分发的请求(通常是 Controller 接口),需手动配置才能拦截静态资源,支持基于注解、路径的细粒度控制

5. 异常处理能力不同

  • 过滤器:抛出的异常无法被 Spring 全局异常处理器(@RestControllerAdvice)捕获,需自行处理(转发错误页或手动写入响应)。
  • 拦截器:抛出的异常可被 Spring 全局异常处理器统一处理,与 Spring 异常体系无缝集成。

6. 适用场景不同

  • 过滤器:适合容器级、全请求通用的无状态处理,如:
    • 请求编码设置(CharacterEncodingFilter
    • CORS 跨域处理
    • XSS/CSRF 攻击防护
    • 全链路 TraceId 透传
  • 拦截器:适合业务级、依赖 Spring 上下文的细粒度处理,如:
    • 登录认证、权限校验
    • 接口访问日志、执行耗时统计
    • 接口幂等性校验
    • 业务级限流、灰度发布控制