根据java案例,拦截数据哪队更好?

wen java案例 5

Java案例实战:拦截数据哪队更好?Filter、Interceptor与AOP深度对决

目录导读


开篇:一个真实Java项目引发的"拦截之争"

在笔者参与过的一个Spring Boot电商项目中,团队曾为"接口请求日志与权限校验"的实现方式争论了整整两天:有人坚持用Filter,有人力挺HandlerInterceptor,还有架构师主张用AOP切面,三方各执一词,代码评审会上几乎"吵"了起来。

根据java案例,拦截数据哪队更好?

这场争论的本质,其实是Java Web开发中一个经典命题——拦截数据,到底哪队更好? 本文结合真实Java案例,从执行时机、作用范围、数据可获取性、性能开销等维度,对Filter、Interceptor、AOP三支"拦截队伍"做一次去伪存真的深度剖析,帮助你在实际项目中做出正确选型。

搜索引擎上关于这个话题的文章不少,但多数停留在概念罗列,缺少可运行案例与场景化对比,本文力求补上这块短板。


三队选手登场:Filter、Interceptor、AOP各是什么

Filter(过滤器) 属于Servlet规范,由容器(如Tomcat)管理,工作在请求进入Servlet之前、响应返回客户端之前,它能拿到原始的HttpServletRequest和HttpServletResponse,但拿不到Spring MVC的处理器信息。

Interceptor(拦截器) 是Spring MVC提供的机制,工作在DispatcherServlet内部,位于HandlerMapping之后、HandlerAdapter调用之前,它可以访问HandlerMethod,知道"即将执行哪个Controller的哪个方法",但拿不到原始Servlet请求的完整包装链。

AOP(面向切面编程) 是Spring的核心能力,基于代理机制作用于方法调用层面,它能精确拦截某个类的某个方法,获取方法参数、返回值、异常,但对HTTP协议层无感知。

三者并非替代关系,而是分层协作关系:Filter在最外层,Interceptor在中间层,AOP在最内层(方法级)。


Java案例实战:同一需求三种写法

假设需求是:统计每个接口的耗时并记录请求URI。

Filter实现

@Component
public class CostFilter 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);
        long cost = System.currentTimeMillis() - start;
        System.out.println(request.getRequestURI() + " 耗时: " + cost + "ms");
    }
}

Interceptor实现

@Component
public class CostInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        request.setAttribute("start", System.currentTimeMillis());
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) {
        long start = (Long) request.getAttribute("start");
        System.out.println(request.getRequestURI() + " 耗时: " + (System.currentTimeMillis() - start) + "ms");
    }
}

AOP实现

@Aspect
@Component
public class CostAspect {
    @Around("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = pjp.proceed();
        System.out.println(pjp.getSignature() + " 耗时: " + (System.currentTimeMillis() - start) + "ms");
        return result;
    }
}

案例结论很直观:统计HTTP请求级耗时,Filter和Interceptor都能胜任;统计方法级耗时(含Service层),只有AOP能做到。


核心维度对比:谁更胜一筹

维度 Filter Interceptor AOP
执行时机 最外层,Servlet之前 DispatcherServlet内 方法调用时
能否拿到HandlerMethod 否 是 是(通过注解)
能否修改请求体 是(需包装) 否 否
作用范围 所有请求(含静态资源) 仅Controller请求 任意Spring Bean方法
异常捕获 难 afterCompletion可捕获 @AfterThrowing精确捕获
性能开销 最低 低 略高(代理)

选型建议:

  • 需要统一编码、跨域、请求体加密解密、SQL注入过滤——选Filter;
  • 需要登录校验、权限注解、Controller级日志——选Interceptor;
  • 需要方法级埋点、事务、缓存、限流切面——选AOP。

一句话总结:Filter管"门",Interceptor管"路",AOP管"点"。


常见问答Q&A

Q1:Filter和Interceptor能同时存在吗?执行顺序如何? A:可以共存,顺序为 Filter → preHandle → Controller → afterCompletion → Filter 后置逻辑,Filter总在最外层。

Q2:拦截数据时,哪个性能更好? A:Filter性能最优,因为它在容器层直接生效;Interceptor次之;AOP因代理机制略有开销,但差异在毫秒级,除非高并发极致场景,否则不必过分纠结。

Q3:为什么很多项目权限校验用Interceptor而不用Filter? A:因为Interceptor能拿到HandlerMethod,可读取方法上的自定义注解(如@RequirePermission),实现细粒度控制,而Filter做不到。

Q4:AOP能替代Interceptor吗? A:不能,AOP作用于方法层,无法拦截静态资源请求、无法在Controller方法执行"之前"就决定是否放行(虽然@Around可以,但拿不到HTTP请求链路的完整信息),两者定位不同。


没有最好,只有最合适

回到开篇的争论:拦截数据哪队更好? 答案不是"某队完胜",而是"按场景分队",Filter守住协议入口,Interceptor把住MVC关卡,AOP深耕方法逻辑,真正成熟的Java架构,往往是三队协同作战,而非单打独斗。

掌握三者的边界与协作方式,比争论谁更强更有价值,希望本文的案例与对比,能让你在下一次技术选型会上,少吵两天架,多写两行好代码。

上一篇根据赛后java案例,停赛球员影响多大?

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!