过滤器/拦截器/AOP 三者区别
结论先行:三者按"离请求的距离"从远到近:Filter(Servlet 规范,最外层)→ HandlerInterceptor(Spring MVC)→ AOP(Spring Bean 方法,最内层)。调用链为:请求 → Filter.doFilter → DispatcherServlet → Interceptor.preHandle → (AOP 包裹的)Controller 方法 → Interceptor.postHandle → 渲染/写回 → Interceptor.afterCompletion → 响应返回 Filter。Filter 拦得住静态资源与所有 URL 但拿不到 HandlerMethod;Interceptor 拿得到 HandlerMethod/ModelAndView 但只管命中 handler 的请求;AOP 最细,但只作用于被 Spring 管理的 Bean 方法调用。
一、对比表
| 维度 | Filter | HandlerInterceptor | AOP |
|---|---|---|---|
| 所属 | Servlet 规范(jakarta.servlet) | Spring MVC | Spring 容器 |
| 拦截对象 | 所有 Web 请求(可含静态资源) | 匹配到 handler 的请求 | 被管理 Bean 的方法调用 |
| 能否改请求/响应 | 能(包装 request/response、放行/拦截 chain) | 不改响应流,可改 modelAndView | 拦截方法参数/返回值 |
| 上下文信息 | 无 handler 细节 | HandlerMethod、ModelAndView | JoinPoint、方法签名 |
| 典型场景 | 字符编码、CORS、粗粒度登录校验、日志 | 登录态、权限、通用 Model 填充 | 事务、缓存、审计、埋点(方法级) |
| 注册方式 | @WebFilter/@Order 或 FilterRegistrationBean | 实现 HandlerInterceptor + WebMvcConfigurer.addInterceptors | @Aspect + 切点表达式 |
二、执行链路示意
// 一次请求的完整链路(示意)
request
→ Filter.doFilter(...) // 容器层:最早进入、最晚退出
→ DispatcherServlet.doDispatch
→ interceptor.preHandle(request, response, handler)
→ (事务/缓存等 AOP 切面) controller.method(...) // 最内层
→ interceptor.postHandle(...) // 渲染前
→ 视图渲染 / @ResponseBody 写回
→ interceptor.afterCompletion(...) // 请求完成后(finally 语义)
→ Filter 链继续 / 返回响应
常见追问 / 记忆点
- 追问 1:登录鉴权放哪层?答:Spring 项目一般放 Interceptor(能拿到 handler/注解做细粒度控制)或 Spring Security 的过滤器链;纯 Web 通用处理(编码、CORS)放 Filter。
- 追问 2:为什么事务不能放 Filter?答:Filter 在 MVC 之外,拿不到 Service 的代理语义,事务应贴在最内层的方法级 AOP 上(@Transactional)。
- 追问 3:三者能重复做一件事吗?答:能但别叠——同一种能力选最贴近业务的层,避免链路重复执行。
- 记忆点:"Filter 拦请求、Interceptor 拦 Handler、AOP 拦方法;越靠内越细、越靠外越全"。