Spring 拦截器(Interceptor)与过滤器(Filter)全解析(2025 版)
继续 Spring MVC 系列!拦截器和过滤器都是 AOP(面向切面编程)的经典实现,用于处理请求/响应,但执行时机、作用域、功能深度完全不同。
Spring Boot 3.x(Spring Framework 6.x)下,配置几乎零门槛,直接复制代码就能用。
一、核心区别对比表(面试/生产必背)
| 维度 | Filter(过滤器) | Interceptor(拦截器) |
|---|---|---|
| 所属规范 | Servlet API(jakarta.servlet.Filter) | Spring MVC(org.springframework.web.servlet.HandlerInterceptor) |
| 执行时机 | 最外层:请求到达 Servlet 容器前/响应返回前(DispatcherServlet 前) | 内层:DispatcherServlet 后,Controller 前/后/完成时 |
| 作用范围 | 所有 Servlet/JSP/静态资源(包括 Spring MVC 外) | 只针对 Spring MVC 的 Handler(Controller 方法) |
| 访问 Spring 容器 | 否(纯 Servlet,不能注入 Bean) | 是(可注入 Service/Repository 等) |
| 方法 | doFilter() | preHandle() / postHandle() / afterCompletion() |
| 顺序控制 | web.xml 或 @Order / FilterRegistrationBean | 注册顺序或 @Order |
| 异常处理 | 可在 doFilter 捕获所有异常 | afterCompletion 可捕获(但 pre/post 抛异常需全局处理) |
| 典型场景 | 编码转换、CORS、安全过滤(Spring Security 就是 Filter 链) | 日志、权限校验(Controller 级)、性能监控 |
| Spring Boot 配置 | @WebFilter + @ServletComponentScan 或 FilterRegistrationBean | WebMvcConfigurer.addInterceptors() |
结论:
- Filter 先执行(外层),适合全局/低级处理(如编码、CORS)。
- Interceptor 后执行(内层),适合 Spring 生态特定逻辑(如访问 ModelAndView)。
- 顺序:Filter → DispatcherServlet → Interceptor pre → Controller → Interceptor post → View → Interceptor after → Filter。
二、执行流程图(一次请求的顺序)
客户端请求
↓
Filter1 doFilter (pre)
↓
Filter2 doFilter (pre)
↓
DispatcherServlet
↓
Interceptor1 preHandle
↓
Interceptor2 preHandle (若返回 false,则中断)
↓
Controller 方法执行
↓
Interceptor2 postHandle
↓
Interceptor1 postHandle
↓
ViewResolver + 视图渲染
↓
Interceptor1 afterCompletion (不管异常)
↓
Interceptor2 afterCompletion
↓
Filter2 doFilter (post)
↓
Filter1 doFilter (post)
↓
响应返回客户端
三、Interceptor 配置 & 使用(Spring Boot 3 推荐)
实现 HandlerInterceptor 接口,重写 3 方法。
// 自定义拦截器(日志 + 权限示例)
@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// pre: 请求前(可拒绝请求)
log.info("preHandle: URL={}", request.getRequestURI());
String token = request.getHeader("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
response.setStatus(401); // 未授权
response.getWriter().write("Unauthorized");
return false; // 中断链
}
// 可注入 Service 校验 token
return true; // 放行
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// post: Controller 后,视图渲染前(可改 ModelAndView)
log.info("postHandle: 添加额外模型");
if (modelAndView != null) {
modelAndView.addObject("extra", "intercepted");
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// after: 完成(清理资源,常用于日志/监控)
log.info("afterCompletion: 执行耗时计算或异常处理");
if (ex != null) {
log.error("异常: {}", ex.getMessage());
}
}
}
注册(实现 WebMvcConfigurer):
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**") // 拦截路径(Ant 风格)
.excludePathPatterns("/api/public/**", "/login"); // 排除
// .order(1); // 指定顺序(可选)
}
}
四、Filter 配置 & 使用(Spring Boot 3)
实现 Filter 接口。
// 自定义过滤器(编码 + CORS 示例)
@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "encodingFilter")
@Order(1) // 执行顺序(值越小越先)
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// pre: 请求前
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
log.info("Filter pre: {}", request.getRequestURI());
// 放行
chain.doFilter(request, response);
// post: 响应后
log.info("Filter post");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化
}
@Override
public void destroy() {
// 销毁
}
}
启用扫描(启动类):
@SpringBootApplication
@ServletComponentScan // 扫描 @WebFilter
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
或用 FilterRegistrationBean(更灵活,可注入 Bean):
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<EncodingFilter> encodingFilter() {
FilterRegistrationBean<EncodingFilter> reg = new FilterRegistrationBean<>();
reg.setFilter(new EncodingFilter());
reg.addUrlPatterns("/*");
reg.setOrder(1);
return reg;
}
}
五、生产级最佳实践(2025 年)
- 登录/权限:Interceptor(可访问 Spring Bean 校验 JWT)。
- 全局编码/CORS/日志:Filter(最外层,覆盖所有)。
- Spring Security:内置 Filter 链,优先用它做认证。
- 多个链:Filter 用 @Order,Interceptor 用注册顺序。
- 异步支持:Filter 加 DispatcherType.ASYNC/ERROR。
- 坑点避坑:
- Interceptor 不能拦截静态资源(用 Filter 或 ResourceHandler)。
- Filter 不能注入 Bean(用 RegistrationBean 包装)。
- 异常:用 @ControllerAdvice 全局捕获。
六、总结推荐
| 场景 | 优先选择 |
|---|---|
| 全局请求修改/安全 | Filter |
| Controller 级逻辑 | Interceptor |
| 混合使用 | Filter 先 + Interceptor 后 |
一句话:Filter 是 Servlet 的门卫,Interceptor 是 Spring MVC 的管家。
现在你能轻松配置了!想看完整登录拦截示例代码?或 AOP @Aspect 替代方案?继续问我,超详细教程等着你!