当前位置: 首页 > news >正文

Spring Boot 拦截器(Interceptor)与过滤器(Filter)有什么区别?

在 Spring Boot 项目中,我们经常会遇到需要在请求处理前后执行一些通用逻辑的场景,比如记录日志、权限校验、全局异常处理等。此时,我们通常会面临两种选择:过滤器(Filter)拦截器(Interceptor)

虽然两者都能实现类似的功能,但它们在实现原理、使用场景、执行时机等方面有着本质的区别。本文将带你深入剖析这两者的差异,并通过实战案例,让你彻底搞懂何时该用过滤器,何时该用拦截器。

在这里插入图片描述

一、核心概念:从根上理解它们的区别

1.1 过滤器(Filter)

  • 规范层级:属于 Java Servlet 规范 的一部分,由 Servlet 容器(如 Tomcat)直接管理。
  • 作用范围:对整个 Web 应用生效,包括静态资源(如 HTML、CSS、JS 等)。
  • 触发时机:在请求进入 DispatcherServlet 之前,以及响应返回客户端之后。
  • 依赖关系:不依赖 Spring 容器,可以脱离 Spring 独立使用。

1.2 拦截器(Interceptor)

  • 规范层级:Spring MVC 框架提供的机制,由 Spring 容器管理。
  • 作用范围:仅对 Spring MVC 控制器(Controller) 的请求生效,默认不拦截静态资源。
  • 触发时机:在请求进入 DispatcherServlet 之后,到达 Controller 之前,以及 Controller 处理完请求之后。
  • 依赖关系:深度集成 Spring 容器,可以方便地使用 Spring 的依赖注入(DI)和 AOP 功能。
特性对比过滤器(Filter)拦截器(Interceptor)
规范层级Java Servlet 规范Spring MVC 框架
作用范围所有请求(包括静态资源)仅 Controller 请求
触发时机DispatcherServlet 前后Controller 前后
依赖容器Servlet 容器Spring 容器
能否修改请求/响应可以直接修改不能直接修改,但可操作 Model 和 View

二、执行流程:一个图看懂它们的调用顺序

为了更直观地理解两者的执行顺序,我们来看一张经典的流程图:

HTTP Request↓
Filter Chain(doFilter)↓
DispatcherServlet↓
Interceptor.preHandle↓
Controller Method↓
Interceptor.postHandle↓
View Rendering(如有)↓
Interceptor.afterCompletion↓
Filter Chain(返回响应)

从这个流程可以看出:

  • 过滤器 是最外层的“大门”,所有请求都必须经过它。
  • 拦截器 是内层的“小门”,只对进入 Spring MVC 的请求生效。

三、实战演练:代码说话最真实

3.1 过滤器(Filter)实战:记录请求耗时

@Component
public class LogFilter implements Filter {private static final Logger logger = LoggerFactory.getLogger(LogFilter.class);@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {long startTime = System.currentTimeMillis();HttpServletRequest httpRequest = (HttpServletRequest) request;logger.info("请求开始,URI: {}", httpRequest.getRequestURI());chain.doFilter(request, response); // 放行请求long duration = System.currentTimeMillis() - startTime;logger.info("请求结束,耗时: {}ms", duration);}
}

3.2 拦截器(Interceptor)实战:登录权限校验

@Component
public class AuthInterceptor implements HandlerInterceptor {@Autowiredprivate AuthService authService; // 可以注入Spring Bean@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String token = request.getHeader("Authorization");if (!authService.isValidToken(token)) {response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);return false; // 拦截请求}return true; // 放行请求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {logger.info("Controller 方法执行完毕,准备渲染视图");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {logger.info("请求处理完成,资源清理");}
}

3.3 配置拦截器到Spring容器

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate AuthInterceptor authInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(authInterceptor).addPathPatterns("/api/**") // 拦截所有 /api 开头的请求.excludePathPatterns("/api/login"); // 排除登录接口}
}

四、选型指南:什么时候用过滤器,什么时候用拦截器?

场景需求推荐方案
需要处理静态资源(如HTML、CSS、JS)过滤器(Filter)
需要最早拦截请求(如全局跨域处理)过滤器(Filter)
需要访问Spring Bean(如Service、Repository)拦截器(Interceptor)
需要精确控制Controller方法的执行前后拦截器(Interceptor)
需要修改请求和响应的内容(如压缩、编码)过滤器(Filter)

五、常见误区与最佳实践

5.1 常见误区

  • 误区1:拦截器可以处理静态资源
    实际上,拦截器默认不会拦截静态资源,除非你手动配置了 addResourceHandler

  • 误区2:过滤器可以直接使用Spring Bean
    过滤器由Servlet容器管理,默认无法使用Spring的依赖注入。可以通过 DelegatingFilterProxy 桥接,但配置较复杂。

  • 误区3:拦截器可以修改请求参数
    拦截器无法直接修改请求参数,如需修改,需使用过滤器配合 HttpServletRequestWrapper

5.2 最佳实践

  • 优先使用拦截器:除非必须处理静态资源或需要最早拦截,否则优先使用拦截器,因为它更贴近业务逻辑,且易于测试。
  • 避免复杂逻辑:无论是过滤器还是拦截器,都应避免复杂的业务逻辑,以免影响性能。
  • 合理配置顺序:如果同时使用多个过滤器或拦截器,务必注意它们的执行顺序,避免逻辑冲突。

六、总结:一句话记住它们的区别

过滤器(Filter)是 Servlet 的“大门”,拦截器(Interceptor)是 Spring MVC 的“小门”。

  • Filter:更早、更底层、更通用,但离业务逻辑较远。
  • Interceptor:更晚、更上层、更灵活,更贴近业务逻辑。
http://www.xdnf.cn/news/1451071.html

相关文章:

  • 【数据可视化-107】2025年1-7月全国出口总额Top 10省市数据分析:用Python和Pyecharts打造炫酷可视化大屏
  • LeetCode每日一题,2025-9-4
  • 动手学深度学习——线性回归 + 基础优化算法
  • 服务器异常负载排查手册 · 隐蔽进程篇
  • Android AI客户端开发(语音与大模型部署)面试题大全
  • Tomcat 服务器全方位指南:安装、配置、部署与实战优化
  • Sentinel 与 Feign 整合详解:实现服务调用的流量防护
  • Clang 编译器:下载安装指南与实用快捷键全解析
  • C++类和对象(上):从设计图到摩天大楼的构建艺术
  • 蔚来汽车前制动器设计及热性能分析cad+三维图+设计说明书
  • MySQL SM4 UDF 安装与使用
  • 【计算机网络(自顶向下方法 第7版)】第一章 计算机网络概述
  • 《D (R,O) Grasp:跨机械手灵巧抓取的机器人 - 物体交互统一表示》论文解读
  • 实战演练(二):结合路由与状态管理,构建一个小型博客前台
  • Java基础知识点汇总(五)
  • 修订版!Uniapp从Vue3编译到安卓环境踩坑记录
  • 新手向:AI IDE+AI 辅助编程
  • 开源视频剪辑工具推荐
  • 经典资金安全案例分享:支付系统开发的血泪教训
  • Hadoop(七)
  • 数说故事 | 2025年运动相机数据报告,深挖主流品牌运营策略及行业趋势​
  • HarmonyOS路由导航方案演进:HMRouter基于Navigation封装,使用更方便
  • 【软考架构】嵌入式系统及软件
  • Shadcn UI – 开发者首选的高性能、高定制化 React 组件库
  • Flutter之riverpod状态管理详解
  • 第1章 Jenkins概述与架构
  • ⸢ 肆 ⸥ ⤳ 默认安全:安全建设方案 ➭ b.安全资产建设
  • HTTP性能优化
  • Rust 文件操作终极实战指南:从基础读写到进阶锁控,一文搞定所有 IO 场景
  • 设计模式3 创建模式之Singleton模式