Filter(过滤器)、Interceptor(拦截器) 和 AOP(面向切面编程)

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 InterceptorAOP 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
    合理分层,避免"用大炮打蚊子"或"力所不能及"。
    三者协同工作,才能构建出层次清晰、职责分明的企业级应用。
相关推荐
oak隔壁找我5 小时前
反向代理详解
后端·架构
YUELEI1185 小时前
Springboot WebSocket
spring boot·后端·websocket
小蒜学长6 小时前
springboot基于JAVA的二手书籍交易系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端
忧郁的蛋~6 小时前
.NET实现多任务异步与并行处理的详细步骤
后端·c#·asp.net·.net·.netcore
CoLiuRs6 小时前
在 go-zero 中优雅使用 Google Wire 实现依赖注入
后端·微服务·golang
野犬寒鸦6 小时前
从零起步学习MySQL || 第七章:初识索引底层运用及性能优化(结合底层数据结构讲解)
java·数据库·后端·mysql·oracle
全职计算机毕业设计6 小时前
基于SpringBoot框架的在线教育系统设计与实现(三套文档参考)
java·spring boot·后端
IT_陈寒7 小时前
Python性能优化:5个被低估但效果惊人的内置函数实战解析
前端·人工智能·后端
千码君20167 小时前
Go语言:对其语法的一些见解
开发语言·后端·golang