过滤器,拦截器,控制器增强器,切面

image

824e582202bc42ea9cfe8824ce7d7668

 

 

过滤器、拦截器、@ControllerAdvice、AOP 切面 完整对比

一、底层归属与执行顺序(核心区分点)

1. 所属层级(从外到内)

  1. Filter 过滤器 → Servlet 规范(Tomcat 容器层面,不属于 Spring)
  2. Interceptor 拦截器 → SpringMVC 组件(DispatcherServlet 内部)
  3. @ControllerAdvice 控制器增强 → SpringMVC 控制器层增强
  4. AOP Aspect 切面 → Spring AOP,Bean 方法层面(Service/Controller 均可)

2. 请求完整执行顺序

浏览器请求 → Tomcat
→ Filter.doFilter() 前置逻辑
→ DispatcherServlet
→ Interceptor.preHandle()
→ Controller方法执行前
    → AOP环绕前置 @Before
    → Controller方法内部
        → 异常抛出 → @ControllerAdvice全局异常处理器
    → AOP环绕后置 @AfterReturning / @AfterThrowing
→ Interceptor.postHandle()(Controller执行完,视图渲染前)
→ 页面渲染
→ Interceptor.afterCompletion()(请求结束)
→ Filter后置逻辑
→ 响应返回浏览器

3. 能否拿到原生对象

组件
HttpServletRequest/Response
Spring 上下文 Model
Controller 入参
方法入参 / 返回值
Filter
✅ 原生 Servlet 对象
❌ 拿不到 Spring Bean
Interceptor
✅ 封装后的 Spring 对象
✅ Model
❌ 拿不到接口方法参数
@ControllerAdvice
✅ 可拿到接口参数
✅ 返回值统一封装
AOP 切面
❌ 无法直接拿 request(需手动注入 RequestContextHolder)
✅ 任意 Bean 方法入参
✅ 任意方法返回值、异常

二、四大组件功能、适用场景、能实现什么

1. Filter 过滤器(Servlet 规范,全局第一层拦截)

核心定位

Tomcat 容器级拦截,所有请求(静态资源、jsp、接口)都会先走 Filter,和 Spring 无关

可实现功能

  1. 统一编码设置(request.setCharacterEncoding)
  2. 跨域 CORS 处理(早期方案)
  3. 请求黑白名单、IP 限流、非法 URL 拦截
  4. 登录基础校验(未登录直接返回,不进入 Spring)
  5. 请求 / 响应流包装(读取原始请求 body,重复消费)
  6. 静态资源过滤、文件上传基础预处理

局限性

  • 拿不到 Controller、Service、方法参数、返回值
  • 不能操作 Spring Bean,无法依赖注入 Service
  • 只能操作原生 Servlet request/response

典型实现

@WebFilter("/*")
public class CorsFilter implements Filter{}

2. HandlerInterceptor 拦截器(SpringMVC 专属,DispatcherServlet 内)

核心定位

只拦截进入 Controller 的请求,静态资源默认不拦截,属于 SpringMVC 组件。

三个执行方法

  1. preHandle:Controller 执行前,返回 false 直接中断请求
  2. postHandle:Controller 执行完毕、视图渲染之前
  3. afterCompletion:整个请求结束,资源释放

可实现功能

  1. 登录 token、权限校验(Spring 环境,可注入 Redis / 用户 Service)
  2. 请求日志打印(请求地址、耗时、用户 ID)
  3. 统一设置返回头信息
  4. 存储当前登录用户到 ThreadLocal
  5. 接口防重复提交(基于 token)
  6. 视图数据统一填充(postHandle 修改 Model)

局限性

  • 无法直接获取 Controller 接口的方法入参、注解
  • 不能拦截 Service 层方法,只能作用 Controller 入口
  • 拿不到方法返回值,无法统一包装返回体

3. @ControllerAdvice 控制器增强(仅作用 Controller 层)

核心定位

SpringMVC 控制器层专属增强,只针对 @Controller/@RestController。 搭配注解:
  • @ExceptionHandler:全局异常处理
  • @InitBinder:请求参数绑定、参数校验、日期格式化
  • @ModelAttribute:所有 Controller 统一注入公共参数

可实现功能

  1. 全局统一异常捕获(业务异常、空指针、参数异常统一返回 JSON)
  2. 请求参数统一格式化(Date、BigDecimal、去除前后空格)
  3. 公共参数自动注入(全局 userId、租户 id 自动塞到所有接口)
  4. 统一响应体封装(所有接口返回统一 Result)
  5. 参数校验统一捕获 @Valid 抛出的 MethodArgumentNotValidException

局限性

  • 只生效 Controller,拦截不到 Service、Mapper 方法
  • 无法拦截静态资源,不能做容器级过滤
  • 无法记录方法执行前后耗时、切面日志

4. AOP Aspect 切面(Spring AOP,任意 Bean 方法拦截)

核心定位

基于动态代理,拦截任意 Spring Bean 的方法(Controller、Service、Mapper 均可),和 MVC 无关。 通知类型:@Before、@AfterReturning、@AfterThrowing、@Around(环绕最强)

可实现功能

  1. 方法级日志(入参、返回值、执行耗时、异常堆栈)
  2. 事务管理(@Transactional 底层就是 AOP)
  3. 接口 / 方法权限校验(注解式权限控制 @RequirePerm)
  4. 接口限流、分布式锁、缓存切面
  5. 操作日志记录(用户操作、修改前后数据对比)
  6. 方法重试、熔断、埋点监控
  7. Service 层统一异常捕获

局限性

  • 默认拿不到原生 HttpServletRequest(需 RequestContextHolder 获取)
  • 不能在请求最前端拦截,无法提前阻断请求返回 response
  • 静态资源完全无法拦截

三、横向对比总表

维度
Filter 过滤器
Interceptor 拦截器
@ControllerAdvice 控制器增强
AOP 切面
所属规范
Servlet 容器
SpringMVC
SpringMVC
Spring AOP
拦截范围
全部请求(静态资源、接口、jsp)
仅 Controller 接口
仅 Controller
所有 Spring Bean 方法(Controller/Service)
执行时机
最外层,最先执行
DispatcherServlet 内部
Controller 方法执行 / 抛出异常时
方法调用前后
获取 request
原生对象直接拿
Spring 封装后直接拿
直接注入
需要工具类获取
获取方法参数
不能
不能
可以
可以(JoinPoint)
获取返回值
不能
不能
可以
可以
依赖注入 Bean
不支持
支持
支持
支持
统一异常处理
很难实现
不擅长
专用,最优解
可实现但不推荐
参数格式化
麻烦
不支持
专用 @InitBinder
不适合
方法耗时、操作日志
只能粗粒度请求日志
粗粒度请求日志
不擅长
最优解
跨域、编码、底层流处理
最优解
不适合
不适合
不适合
登录权限校验
简单轻量校验
业务权限首选
不适合拦截校验
注解式权限校验

四、业务场景选型建议(开发常用)

  1. 统一编码、跨域、读取原始 RequestBody → Filter
  2. 登录 Token 校验、全局请求日志、存储登录用户 → Interceptor
  3. 全局异常统一返回、参数格式化、统一返回体封装 → @ControllerAdvice
  4. 方法耗时日志、操作记录、注解权限、缓存、事务、重试 → AOP 切面

五、经典区分面试简答

  1. Filter 是 Tomcat 层面,早于 Spring,处理底层流、编码;
  2. Interceptor 是 SpringMVC,专门做接口登录鉴权;
  3. ControllerAdvice 只管控制器异常、参数绑定、统一返回;
  4. AOP 是方法层面,面向所有 Bean,做日志、缓存、事务等通用业务逻辑。

 

posted @ 2026-07-02 14:02  ConfidentLiu  阅读(10)  评论(0)    收藏  举报