Filter、Interceptor 与 AOP 的区别
在 Java Web 开发中,Filter(过滤器) 、Interceptor(拦截器) 和 AOP(面向切面编程) 都可以实现"横切关注点"(如日志、权限、事务、性能监控等),但它们作用层级、技术原理、适用场景完全不同。下面从多个维度进行系统对比:
🌐 一、整体定位与作用层级
机制 | 所属规范/框架 | 作用层级 | 作用范围 |
---|---|---|---|
Filter | Java EE(Servlet 规范) | Web 容器层(Tomcat/Jetty) | 所有进入 Servlet 容器的 HTTP 请求(包括静态资源) |
Interceptor | Spring MVC | Web 框架层(DispatcherServlet 内部) | 仅 Spring Controller 处理的请求 |
AOP | Spring(或 AspectJ) | 业务逻辑层 / 方法调用层 | Spring 管理的 Bean 中的方法调用(不限于 Web) |
🔺 层级关系(从外到内) :
Filter → Interceptor → Controller → AOP(Service 层方法)
⏱️ 二、执行流程示意图
text
Client
↓
[ Filter (doFilter 前) ]
↓
DispatcherServlet
↓
[ Interceptor.preHandle() ]
↓
Controller.method()
│
└─→ 调用 Service.method()
↓
[ AOP @Before ]
↓
Service 业务逻辑
↓
[ AOP @After / @AfterReturning ]
↓
[ Interceptor.postHandle() ]
↓
View 渲染
↓
[ Interceptor.afterCompletion() ]
↓
[ Filter (doFilter 后) ]
↓
Response → Client
✅ 执行顺序: Filter → Interceptor → Controller → AOP → ... → Interceptor → Filter
🔍 三、核心区别对比表
💡 四、典型使用场景举例
1. Filter
- 设置请求编码:request.setCharacterEncoding("UTF-8")
- 添加安全响应头:X-Content-Type-Options: nosniff
- 跨域处理(CORS)
- 全局请求日志(记录 IP、URL、User-Agent)
2. Interceptor
- 检查用户是否登录(从 token 获取用户信息)
- 记录 API 调用日志(含用户 ID、接口名)
- 接口权限校验(如 @RequiresRole("admin"))
- 防重复提交(通过 token)
3. AOP
- 事务管理:@Transactional(本质是 AOP)
- 服务层日志:记录方法入参、返回值、耗时
- 缓存:@Cacheable、@CacheEvict
- 异常统一处理:捕获业务异常并转换
- 性能监控:统计方法执行时间
五、能否互相替代?
场景 | 能否用 AOP 替代 Interceptor? | 能否用 Interceptor 替代 Filter? |
---|---|---|
记录 HTTP 请求头(如 User-Agent、Referer) | ❌ AOP 无法直接访问 HttpServletRequest |
✅ Interceptor 可获取请求对象,能实现 |
在 Service 方法上添加事务管理 | ✅ AOP 是标准做法(如 @Transactional ) |
❌ Interceptor 作用于 Controller 层,无法控制 Service 方法 |
拦截静态资源请求(如 /static/js/app.js ) |
❌ AOP 不处理 HTTP 请求 | ✅ 只有 Filter 能拦截静态资源 |
根据 Controller 方法上的自定义注解做权限校验(如 @RequiresRole("admin") ) |
⚠️ 理论可行但复杂(需反射+代理),不推荐 | ✅ Interceptor 可通过 HandlerMethod 获取方法和注解,天然支持 |
修改请求体内容(如解密加密参数) | ❌ AOP 无法修改原始 HTTP 流 | ✅ Filter 可通过 HttpServletRequestWrapper 包装并重写 getInputStream() 实现 |
统一处理业务异常并返回 JSON 错误 | ⚠️ AOP 可捕获异常,但无法设置 HTTP 状态码或响应头 | ✅ Interceptor 的 afterCompletion 或配合 @ControllerAdvice 更合适,Filter 也可实现但粒度粗 |
需要访问 Spring Bean(如 UserService) | ✅ AOP 是 Spring Bean,可直接注入 | ✅ Interceptor 是 Spring Bean,可直接注入;Filter 默认不能,需借助 DelegatingFilterProxy |
✅ 结论 :三者定位不同,不可简单互相替代,应根据技术层级和需求选择。
🛠️ 六、代码示例对比
Filter(Servlet)
java
@WebFilter("/*")
public class CorsFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
chain.doFilter(req, res);
}
}
Interceptor(Spring MVC)
java
@Component
public class AuthInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
String token = req.getHeader("Authorization");
if (!isValid(token)) {
res.sendError(401);
return false;
}
return true;
}
}
AOP(Spring)
java
@Aspect
@Component
public class LogAspect {
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
System.out.println("Method " + joinPoint.getSignature() + " took " + (System.currentTimeMillis() - start) + "ms");
return result;
}
// 或作用于 Service
@Around("execution(* com.example.service.*.*(..))")
public Object serviceLog(ProceedingJoinPoint joinPoint) throws Throwable {
// 记录 Service 方法日志
return joinPoint.proceed();
}
}
七、总结:如何选择?
需求场景 | 推荐机制 | 理由 |
---|---|---|
设置请求/响应编码(如 UTF-8) | Filter | 作用于最外层,确保早期生效 |
跨域(CORS)处理 | Filter | 需在预检请求(OPTIONS)阶段响应,Interceptor 无法处理非 Controller 请求 |
添加安全响应头(如 X-Frame-Options , Content-Security-Policy ) |
Filter | 对所有响应生效,包括错误页面和静态资源 |
全局请求日志(记录 IP、URL、耗时) | Filter | 覆盖所有请求,包括 404、静态资源等 |
用户登录态校验(基于 Token/Cookie) | Interceptor | 仅需保护 API 接口,可结合 @RequestMapping 路径匹配 |
基于方法注解的权限控制(如 @PreAuthorize ) |
Interceptor 或 AOP | Interceptor 适合 Web 层权限;AOP 适合服务层细粒度权限 |
记录 API 调用日志(含用户 ID、操作类型) | Interceptor | 可在 preHandle 获取用户上下文,在 afterCompletion 记录结果 |
事务管理(@Transactional ) |
AOP | Spring 声明式事务基于 AOP 实现,是标准方案 |
Service 方法性能监控 | AOP | 可精确切入任意业务方法,统计执行时间 |
缓存操作(如 @Cacheable ) |
AOP | Spring Cache 基于 AOP,自动处理缓存逻辑 |
统一异常处理并返回结构化错误 | AOP + @ControllerAdvice |
AOP 可捕获异常,@ControllerAdvice 可统一返回 JSON,比 Filter/Interceptor 更语义化 |
防重复提交(Token 机制) | Interceptor | 可在进入 Controller 前校验并消费 Token |
修改方法入参或返回值(如脱敏、加密) | AOP(@Around ) |
只有 AOP 能在方法执行前后灵活修改参数和返回值 |
💡 最佳实践原则:
- 越底层、越通用的处理 → 用 Filter
- Web 层控制逻辑(与 HTTP 强相关)→ 用 Interceptor
- 业务逻辑切面(与方法调用相关)→ 用 AOP
合理分层,避免"用大炮打蚊子"或"力所不能及"。
三者协同工作,才能构建出层次清晰、职责分明的企业级应用。