在SpringBoot项目中,拦截器(Interceptor)、过滤器(Filter)和AOP(Aspect Oriented Programming)经常让开发者产生选择困难。本文将结合实战场景和代码示例,解析三者的核心差异及最佳使用姿势。
一、概念速览
1. 过滤器(Filter)
Servlet规范定义,基于函数回调实现,作用于Web容器层面。所有请求进入DispatcherServlet前必经之路。
典型场景:
- 全局字符编码设置
- XSS攻击防御
- 敏感词过滤
- 请求耗时统计
@Component
public class CharsetFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
}
2. 拦截器(Interceptor)
Spring MVC机制,基于反射实现,可获取Spring上下文中的Bean。
典型场景:
- 接口权限验证
- 用户登录状态检查
- API请求日志记录
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) {
String token = request.getHeader("Authorization");
return checkToken(token); // 返回false终止请求
}
}
// 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor()).addPathPatterns("/api/**");
}
}
3. AOP
面向切面编程,基于动态代理实现,可切入任意Spring管理的Bean。
典型场景:
- 服务层方法执行日志
- 数据库事务管理
- 接口性能监控
- 业务操作审计
@Aspect
@Component
public class LogAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
System.out.println(joinPoint.getSignature() + " 执行耗时: " + duration + "ms");
return result;
}
}
二、核心差异对比
维度 | 过滤器(Filter) | 拦截器(Interceptor) | AOP |
作用层级 | Servlet容器 | Spring MVC | Spring Bean |
依赖框架 | Servlet规范 | Spring MVC | Spring AOP |
获取上下文 | 无法获取Spring Bean | 可以获取Spring上下文 | 直接操作Bean对象 |
执行顺序 | 最先执行 | 在DispatcherServlet之后 | 方法调用前后 |
处理粒度 | 请求级别 | 请求级别 | 方法级别 |
性能影响 | 低 | 中 | 动态代理带来轻微性能损耗 |
三、实战选择指南
1.必须使用过滤器的场景
- 需要处理所有请求(包括静态资源)
- 需要修改请求/响应内容(如压缩响应)
- 需要处理非Spring管理的资源
2.优先选择拦截器的场景
- 需要访问HandlerMethod等Spring MVC对象
- 需要细粒度控制请求路径(通过PathPattern)
- 需要处理与HTTP协议强相关的逻辑
3.AOP更适合的场景
- 需要处理业务无关的横切关注点
- 需要切入Service/Dao层方法
- 需要灵活控制切入点(注解/包路径等)
四、组合使用案例:API安全防护
// 1. Filter处理XSS攻击
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) {
chain.doFilter(new XssRequestWrapper((HttpServletRequest) request), response);
}
}
// 2. Interceptor验证JWT
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) {
return validateJWT(request.getHeader("Authorization"));
}
}
// 3. AOP记录敏感操作
@Aspect
@Component
public class AuditAspect {
@AfterReturning(pointcut = "@annotation(auditLog)", returning = "result")
public void auditLog(AuditLog auditLog, Object result) {
// 记录操作日志到数据库
}
}
五、避坑指南
- 执行顺序问题:
- 过滤器链顺序:通过@Order控制
- 拦截器顺序:通过registry.addInterceptor()顺序控制
- AOP顺序:通过@Order注解指定
- 性能陷阱:
- 避免在过滤器中处理复杂业务
- 拦截器preHandle中不要阻塞IO
- AOP切入点表达式不要过于宽泛
- 上下文限制:
- 过滤器中无法使用@Autowired
- AOP无法拦截private方法
- 静态方法无法被AOP切入
结语
三者的选择没有绝对标准,关键要抓住本质差异:
- 过滤器是Web容器的守门人
- 拦截器是Spring MVC的安检员
- AOP是业务逻辑的监视器
在实际项目中,通常三者会配合使用:过滤器处理底层协议问题,拦截器处理Web层逻辑,AOP处理业务层横切关注点。掌握它们的差异,才能写出更优雅、更高效的代码。