Spring Boot Filter、Interceptor、AOP 的使用场景与选型

在 Spring Boot 应用程序开发中,Filter(过滤器)、Interceptor(拦截器)和 AOP(面向切面编程)是三种常见的横切关注点实现方式。

它们各有特点和适用场景,正确的选择和使用这些技术对于构建高质量的应用程序至关重要。

一、基本概念与执行顺序

1. Filter(过滤器)

Filter 是 Servlet 规范中定义的组件,位于 Web 容器中,在请求到达 Servlet 之前和响应返回客户端之前进行处理。

@Component
public class LogFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        
        log.info("请求URL: {}", req.getRequestURI());
        
        // 继续执行过滤器链
        chain.doFilter(request, response);
        
        log.info("响应已完成");
    }
}

2. Interceptor(拦截器)

Interceptor 是 Spring MVC 框架提供的组件,位于 DispatcherServlet 之后,Controller 处理之前。

@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
                            Object handler) throws Exception {
        // 在Controller方法执行前调用
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }
        return true;
    }
    
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
                          Object handler, ModelAndView modelAndView) throws Exception {
        // 在Controller方法执行后,视图渲染前调用
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
                               Object handler, Exception ex) throws Exception {
        // 在整个请求完成后调用
    }
}

3. AOP(面向切面编程)

AOP 是 Spring 框架提供的一种编程范式,可以在不修改源代码的情况下为方法添加功能。

@Aspect
@Component
public class PerformanceAspect {
    @Around("execution(* com.example.service.*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        
        Object result = joinPoint.proceed();
        
        long executionTime = System.currentTimeMillis() - start;
        log.info("{} 执行耗时 {} ms", joinPoint.getSignature(), executionTime);
        
        return result;
    }
}

执行顺序

请求处理的顺序为:Filter -> Interceptor -> AOP -> Controller -> AOP -> Interceptor -> Filter

二、使用场景对比

特性

Filter

Interceptor

AOP

作用范围

所有请求

匹配的URL请求

指定的方法

实现层面

Servlet容器

Spring MVC

Spring容器

能否获取方法及类信息

应用场景

请求过滤、字符编码等

用户认证、日志记录等

事务、日志、权限等

三、使用场景分析

1. Filter 适用场景

请求/响应预处理:如字符编码设置、CORS跨域处理 请求内容转换:如请求体解析、加解密 身份验证:如JWT令牌验证 日志记录:记录所有请求的访问日志 敏感信息过滤:过滤敏感词汇

@Component
public class EncodingFilter 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 适用场景

用户认证:检查用户是否已登录 权限控制:检查用户是否有权限访问特定资源 性能监控:监控控制器方法执行时间 日志记录:记录请求处理过程中的详细信息 国际化处理:根据请求设置语言环境

@Component
public class PermissionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
                            Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        RequiresPermission annotation = handlerMethod.getMethodAnnotation(RequiresPermission.class);
        
        if (annotation != null) {
            String requiredPermission = annotation.value();
            // 检查用户权限
            if (!hasPermission(request, requiredPermission)) {
                response.setStatus(HttpStatus.FORBIDDEN.value());
                return false;
            }
        }
        
        return true;
    }
    
    private boolean hasPermission(HttpServletRequest request, String permission) {
        // 权限检查逻辑
        return true;
    }
}

3. AOP 适用场景

事务管理:方法执行前开启事务,执行后提交或回滚 方法性能监控:记录方法执行时间 日志记录:记录方法调用的参数和返回值 缓存处理:方法执行前查询缓存,执行后更新缓存 异常处理:统一处理特定异常

@Aspect
@Component
public class CacheAspect {
    @Autowired
    private CacheManager cacheManager;
    
    @Around("@annotation(com.example.annotation.Cacheable)")
    public Object cache(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Cacheable cacheable = method.getAnnotation(Cacheable.class);
        
        String cacheKey = generateCacheKey(joinPoint, cacheable);
        Object cachedValue = cacheManager.get(cacheKey);
        
        if (cachedValue != null) {
            return cachedValue;
        }
        
        Object result = joinPoint.proceed();
        cacheManager.put(cacheKey, result);
        
        return result;
    }
    
    private String generateCacheKey(ProceedingJoinPoint joinPoint, Cacheable cacheable) {
        // 生成缓存键
        return cacheable.value();
    }
}

四、选型指南

何时选择 Filter:

  1. 需要处理所有的 HTTP 请求
  2. 需要在请求到达控制器之前进行预处理
  3. 处理与 Servlet 规范相关的功能
  4. 需要修改请求或响应对象
  5. 实现框架无关的功能

何时选择 Interceptor:

  1. 需要访问 Spring MVC 特定的功能
  2. 需要访问控制器的上下文
  3. 只需拦截匹配的 URL 请求
  4. 需要灵活的请求拦截配置
  5. 需要多个处理阶段(前置、后置、完成后)

何时选择 AOP:

  1. 需要拦截特定方法的执行
  2. 需要处理业务逻辑层的横切关注点
  3. 需要访问方法的参数和返回值
  4. 需要更细粒度的控制
  5. 非 Web 层的功能增强

五、最佳实践

1. 组合使用

在实际项目中,这三种技术往往会组合使用:

Filter:处理通用的 Web 请求处理,如编码设置、CORS 配置 Interceptor:处理与用户认证、授权相关的功能 AOP:处理业务层面的横切关注点,如日志、性能监控、事务等

2. 性能考虑

  • Filter 和 Interceptor 主要用于 Web 层,每个请求只会经过一次
  • AOP 可能会作用于多个方法,影响更多的调用点
  • 在高并发场景下,应尽量减少 AOP 切面的数量和复杂度

3. 代码组织

将不同横切关注点的实现分离:

  • 认证授权相关的逻辑放在 Interceptor 中
  • 日志、监控等通用功能可以使用 AOP 实现
  • 请求预处理、编码设置等通用功能使用 Filter 实现

六、总结

选择合适的技术取决于具体需求、性能考虑和团队熟悉度。在实际应用中,合理组合使用这三种技术可以构建更加模块化、可维护的应用程序。

对于 Spring Boot 应用程序,推荐遵循"责任分离"原则,根据横切关注点的性质选择最合适的实现方式,让代码结构更加清晰,逻辑更加分明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值