Spring过滤器与拦截器#
一句话答案#
Filter 基于 Servlet 规范拦截请求/响应(Tomcat 级),Interceptor 基于 Spring MVC 拦截 Controller 方法(更细粒度)。
核心要点
Filter vs Interceptor 对比:
| 维度 | Filter | Interceptor |
|---|---|---|
| 规范/归属 | Servlet 规范(jakarta.servlet.Filter),由 Tomcat 等容器调用 | Spring MVC(HandlerInterceptor),由 DispatcherServlet 调用 |
| 位置 | DispatcherServlet 之前 | DispatcherServlet 内部,Handler 调用前后 |
| 拦截范围 | 按 URL 映射,可覆盖静态资源等所有进入容器的请求 | 只拦截 HandlerMapping 匹配到 Handler 的请求 |
| 回调 | doFilter() 一个方法包住整个请求 | preHandle / postHandle / afterCompletion |
| 能拿到的信息 | 只有 Request/Response | 还能拿到 Handler(HandlerMethod:方法签名、注解)和 ModelAndView |
| 典型用途 | 编码、CORS、XSS、Spring Security | 登录校验、操作日志、接口耗时、权限注解判断 |
执行顺序:Filter 链 → DispatcherServlet → Interceptor.preHandle → Controller → postHandle → 视图渲染 → afterCompletion → Filter 链返回。
Filter 的典型应用:Spring Security 过滤链
Spring Security 基于 Servlet Filter Chain 实现,但不是直接注册多个 Servlet Filter,而是用一个 DelegatingFilterProxy 委托给 Spring 管理的 FilterChainProxy:
HTTP 请求
→ DelegatingFilterProxy(Servlet Filter,桥接 Spring)
→ FilterChainProxy(Spring Bean,管理多条 SecurityFilterChain)
→ SecurityFilterChain(匹配 URL 模式,包含 15+ 个内部 Filter)
→ SecurityContextHolderFilter // 加载 SecurityContext(Security 6 默认;旧的 SecurityContextPersistenceFilter 已废弃)
→ UsernamePasswordAuthenticationFilter // 表单登录
→ BearerTokenAuthenticationFilter // JWT/OAuth2 Token 认证
→ AuthorizationFilter // URL 级权限校验(@PreAuthorize 属于方法级安全,走 AOP 方法拦截器,不在这里)
→ ExceptionTranslationFilter // 认证/授权异常处理
→ ...plaintext关键设计:
- 多条 SecurityFilterChain:可以为不同 URL 配置不同的安全策略(如
/api/**用 JWT,/admin/**用 Session) - Filter 顺序固定:Spring Security 内部 Filter 有严格的顺序,不能随意调整
- 自定义 Filter:可以通过
addFilterBefore/After插入自定义过滤器(如自定义 JWT 验证逻辑)
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}java与 JWT 的关系(→ 衔接 JWT原理与实践):
- JWT 认证通常通过自定义
OncePerRequestFilter实现 - 从请求头提取 Token → 解析验证 → 构建
Authentication对象 → 放入SecurityContext - 后续的
AuthorizationFilter基于 SecurityContext 中的权限信息做访问控制
面试回答(2分钟版)
Filter 和 Interceptor 虽然都能拦截请求,但层次和机制不同。Filter 是 Servlet 规范定义的,由 Tomcat 等容器管理,作用于 DispatcherServlet 之前,能拦截所有请求包括静态资源,典型用途是字符编码设置、XSS 过滤、Spring Security 的安全过滤链。Interceptor 是 Spring MVC 提供的,作用在 DispatcherServlet 内部、Controller 方法调用前后,只拦截经过 HandlerMapping 匹配的请求,它能拿到 Handler 和 ModelAndView 信息。执行顺序是 Filter 先执行,然后请求到达 DispatcherServlet,再执行 Interceptor 的 preHandle,接着调用 Controller,之后依次执行 postHandle 和 afterCompletion。选型上,通用的请求预处理如编码、安全用 Filter,和业务相关的如登录校验、操作日志、权限判断用 Interceptor。Spring Security 本质就是一条由多个 Filter 组成的安全过滤链,通过 DelegatingFilterProxy 桥接到 Spring 容器管理。
追问与易错
追问方向:
- “Filter 和 Interceptor 谁先执行?”→ Filter 先执行(Servlet 容器级别,在 DispatcherServlet 之前),Interceptor 后执行(Spring MVC 级别,在 DispatcherServlet 内部、Controller 调用前后)
- “什么场景用哪个?”→ 通用请求预处理(字符编码、CORS、XSS 过滤、安全认证)用 Filter;与业务相关的处理(登录校验、操作日志、接口耗时统计、权限判断)用 Interceptor,因为能拿到 Handler 信息
- “preHandle 返回 false 会怎样?”→ 请求被拦截,后续的 Interceptor 和 Controller 都不会执行;但已执行过 preHandle 的 Interceptor 的 afterCompletion 方法仍会被调用(用于资源清理)
易错点:
- ❌ Filter 和 Interceptor 功能一样——基础不同
- ❌ Interceptor 能拿到方法参数值——preHandle 能拿到 HandlerMethod(方法签名、注解),但拿不到参数解析后的实际值