Java案例实战:拦截数据哪队更好?Filter、Interceptor与AOP深度对比
目录导读
- 为什么"拦截数据"总让Java开发者纠结?
- 三队选手登场:Filter、Interceptor、AOP各自的定位
- 基于Java案例的拦截效果实测
- 问答环节:开发者最关心的5个问题
- 拦截数据哪队更好?
- 最佳实践建议
为什么"拦截数据"总让Java开发者纠结?
在Java Web开发中,"拦截数据"是一个绕不开的话题,无论是记录请求日志、校验用户权限、做参数脱敏,还是统计接口耗时,开发者都需要在请求到达业务逻辑之前或之后插入一段"横切逻辑"。

问题在于,Spring生态里能实现拦截的手段不止一种:Filter、Interceptor、AOP(切面),甚至还有ControllerAdvice、RequestBodyAdvice等,很多团队在技术选型时争论不休,有人说Filter最底层最可靠,有人说Interceptor更灵活,也有人说AOP才是正统。
根据Java案例,拦截数据哪队更好? 本文不站队、不空谈,而是通过真实可运行的代码案例,把三队选手拉到同一场景下比拼,最终给出选型结论。
三队选手登场:Filter、Interceptor、AOP各自的定位
1 Filter(过滤器)
Filter属于Servlet规范,运行在Servlet容器层面(如Tomcat),它在请求进入DispatcherServlet之前生效,能拿到原始的HttpServletRequest,但拿不到Controller方法的元信息(比如方法名、参数注解)。
典型场景:字符编码设置、跨域处理、请求体包装、全局XSS过滤。
2 Interceptor(拦截器)
Interceptor是Spring MVC提供的机制,运行在DispatcherServlet之后、Controller方法之前,它能拿到HandlerMethod,因此可以获取目标方法、类上的注解。
典型场景:登录校验、权限注解解析、接口耗时统计。
3 AOP(面向切面编程)
AOP基于Spring代理机制,作用于Bean方法调用层面,它不限于Web请求,任何Spring Bean的方法都能被增强,能拿到方法参数、返回值、异常。
典型场景:操作日志记录、事务管理、分布式锁、参数脱敏。
三者的执行顺序大致为:Filter → Interceptor → AOP → Controller → AOP → Interceptor → Filter。
基于Java案例的拦截效果实测
下面用一个统一场景来对比:拦截所有请求,打印请求URI和耗时,并对特定方法做参数脱敏。
1 Filter实现
public class LogFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
long start = System.currentTimeMillis();
chain.doFilter(req, res);
System.out.println("Filter耗时:" + (System.currentTimeMillis() - start)
+ "ms, URI=" + request.getRequestURI());
}
}
优点:最底层,能拿到原始请求;缺点:无法获取Controller方法信息,脱敏需手动解析JSON,成本高。
2 Interceptor实现
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
request.setAttribute("startTime", System.currentTimeMillis());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) {
long start = (long) request.getAttribute("startTime");
System.out.println("Interceptor耗时:" + (System.currentTimeMillis() - start)
+ "ms, handler=" + handler);
}
}
优点:可获取HandlerMethod,便于结合注解做权限判断;缺点:只能作用于MVC请求,无法覆盖Service层调用。
3 AOP实现
@Aspect
@Component
public class LogAspect {
@Around("@annotation(logAnno)")
public Object around(ProceedingJoinPoint pjp, LogAnno logAnno) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
System.out.println("AOP耗时:" + (System.currentTimeMillis() - start)
+ "ms, method=" + pjp.getSignature().getName());
return result;
}
}
优点:粒度最细,可精确到方法、参数、返回值;缺点:代理机制对同类内部调用失效,性能略高于前两者。
4 实测对比表
| 维度 | Filter | Interceptor | AOP |
|---|---|---|---|
| 作用层级 | Servlet容器 | Spring MVC | Spring Bean |
| 能否拿到方法信息 | 否 | 是 | 是 |
| 能否拿到参数值 | 需手动解析 | 有限 | 是 |
| 覆盖范围 | 所有请求 | MVC请求 | 所有Bean方法 |
| 执行顺序 | 最先 | 中间 | 最后 |
| 性能开销 | 最低 | 低 | 中 |
问答环节:开发者最关心的5个问题
Q1:只做登录校验,选哪个? A:优先Interceptor,因为它能读取方法注解,且不依赖代理,配置简单。
Q2:需要记录完整请求参数和返回值,选哪个?
A:选AOP,ProceedingJoinPoint能直接拿到参数数组和返回值,最省事。
Q3:需要修改请求体(如解密、脱敏)怎么办?
A:必须用Filter,因为只有它在请求进入MVC前能包装HttpServletRequest,Interceptor和AOP阶段请求体已被读取。
Q4:三队能同时用吗?会不会冲突? A:可以同时用,注意职责划分:Filter管编码和跨域,Interceptor管权限,AOP管日志和事务,互不干扰。
Q5:性能上谁更好? A:Filter最快,Interceptor次之,AOP因代理有一定开销,但在常规业务中差异可忽略。
拦截数据哪队更好?
问题:根据Java案例,拦截数据哪队更好?
答案不是"某一队绝对更好",而是按场景分队:
- 要拿到原始请求、修改请求体 → Filter队赢;
- 要基于注解做权限、登录校验 → Interceptor队赢;
- 要记录方法参数、返回值、异常 → AOP队赢。
真正的高手从不在三者中二选一,而是让它们各司其职、协同工作,一个成熟的Java项目,Filter、Interceptor、AOP往往同时存在,分别负责不同层次的横切关注点。
最佳实践建议
- 编码、跨域、请求包装统一放Filter;
- 认证、授权、接口限流放Interceptor;
- 操作日志、事务、缓存、脱敏放AOP;
- 避免在Filter里做业务判断,避免在AOP里做请求体解析;
- 拦截逻辑要保持单一职责,便于测试与维护。
选型的关键不是"哪队更强",而是"哪队更合适",理解三者的执行时机与能力边界,才能在实际项目中做出最优决策。