基于本文回答
0
评论

Spring MVC拦截器与过滤器核心区别

知识点图片

Filter是Servlet规范,拦截范围广,执行早。Interceptor是Spring组件,只拦截Controller,粒度细,可访问Spring上下文。

这是一个非常经典且重要的面试题。Spring MVC的拦截器(Interceptor)和过滤器(Filter)都是面向切面编程(AOP)的实现,它们允许我们在请求处理的过程中执行一些通用操作,如日志记录、权限检查、性能监控等。

尽管它们功能相似,但在来源、执行时机、作用范围和功能粒度上有本质的区别。


核心区别概览

为了方便理解,我们先用一个表格来总结它们的核心区别:

特性 Filter (过滤器) Interceptor (拦截器)
来源 (Origin) Servlet规范 (Java EE标准) Spring MVC框架
依赖 (Dependency) Servlet容器 (如Tomcat) Spring容器 (IoC)
拦截范围 (Scope) 拦截所有进入容器的请求 只拦截通过DispatcherServlet的请求
执行时机 (Lifecycle) DispatcherServlet之前和之后 DispatcherServlet内部,Controller方法调用前后
可访问资源 (Access) 只能访问Servlet的RequestResponse 可以访问Spring上下文、Bean、Controller的HandlerModelAndView
控制粒度 (Granularity) 粗粒度,基于URL模式(url-pattern) 细粒度,可针对特定Handler(Controller)
实现方式 (Implementation) 实现javax.servlet.Filter接口 实现org.springframework.web.servlet.HandlerInterceptor接口

详细解释

1. 来源和依赖不同 (Origin & Dependency)

  • Filter (过滤器)

    • 来源FilterJava Servlet规范的一部分,定义在javax.servlet.Filter接口中。它不是Spring特有的功能,任何遵循Servlet规范的Web容器(如Tomcat、Jetty)都支持它。
    • 依赖:它由Servlet容器管理,不依赖于Spring容器。因此,在Filter中你无法直接注入Spring管理的Bean(如Service、Repository)。
  • Interceptor (拦截器)

    • 来源InterceptorSpring MVC框架提供的,定义在org.springframework.web.servlet.HandlerInterceptor接口中。
    • 依赖:它由Spring容器管理,本身就是一个Bean。因此,你可以轻松地在Interceptor使用@Autowired等注解注入任何Spring Bean,这使得实现复杂的业务逻辑(如权限校验)变得非常方便。

2. 拦截范围和执行时机不同 (Scope & Lifecycle)

这是最核心的区别。我们可以通过一个请求的处理流程图来理解:

请求流程: Client -> Container -> Filter -> DispatcherServlet -> Interceptor -> Controller

  • Filter (过滤器)

    • 执行时机Filter在请求进入Servlet容器后,但在请求到达DispatcherServlet之前被调用。响应返回给客户端之前,它也会被调用。
    • 拦截范围Filter的拦截范围比Interceptor更广。它可以拦截所有类型的请求,包括静态资源(如.js, .css, .jpg)和非Spring MVC处理的Servlet请求。它的作用域是整个Web应用。
  • Interceptor (拦截器)

    • 执行时机Interceptor工作在DispatcherServlet内部。它只拦截发送到Controller的请求,提供了更精细的控制点:
      1. preHandle: 在Controller方法执行之前调用。可以用于权限检查、日志记录等。如果返回false,则请求处理将在此中断。
      2. postHandle: 在Controller方法执行之后,但在视图(View)渲染之前调用。可以用于修改ModelAndView对象,向视图添加公共数据。
      3. afterCompletion: 在整个请求完成(包括视图渲染)之后调用。主要用于资源清理工作,无论是否发生异常都会执行。
    • 拦截范围:它只拦截通过DispatcherServlet分发的请求。对于静态资源(如果配置为不通过DispatcherServlet)或者直接访问其他Servlet的请求,Interceptor是无能为力的。

3. 可访问的资源和功能粒度不同 (Access & Granularity)

  • Filter (过滤器)

    • 功能Filter可以获取原始的HttpServletRequestHttpServletResponse对象。这意味着它可以修改请求的Header、Body等内容,甚至可以替换Request/Response对象。
    • 限制:它对Spring MVC一无所知,不知道哪个Controller或哪个方法将处理该请求。
  • Interceptor (拦截器)

    • 功能Interceptor可以访问更多Spring MVC的内部信息。
      • preHandle中,它可以获取即将执行的Handler(通常是Controller方法对象),从而可以根据方法上的注解进行特定操作。
      • postHandle中,它可以获取ModelAndView对象,方便地向所有页面添加公共模型数据。
    • 优势:由于它在Spring容器中,可以轻松调用其他业务逻辑组件(Service),实现更复杂的、与业务紧密集成的横切关注点。

总结:何时使用它们?

根据它们的特性,我们可以得出以下最佳实践:

使用Filter的场景:

通常用于处理与框架无关的、全局性的、底层的基础任务。

  • 字符编码过滤:统一设置请求和响应的编码。
  • CORS跨域处理:在响应头中添加CORS相关的Header。
  • XSS攻击防护:过滤请求中的恶意脚本。
  • 数据压缩:对响应内容进行GZIP压缩。
  • 全局日志记录:记录所有进入应用的HTTP请求。

使用Interceptor的场景:

通常用于处理与Spring MVC应用业务逻辑相关的、更细粒度的任务。

  • 登录认证与权限校验:检查用户是否登录,以及是否有权限访问某个Controller方法。
  • 日志记录:记录哪个用户调用了哪个Controller方法,传入了什么参数。
  • 性能监控:计算特定Controller方法的执行时间。
  • 添加通用数据:向所有页面的Model中添加公共信息,如当前登录用户名、导航栏数据等。

简单来说:

  • Filter 是一个“门卫”,负责Web应用的入口,处理最基础和通用的任务。
  • Interceptor 是一个“管家”,在Spring MVC的房子里工作,对进入房子的客人(请求)进行更精细化的管理和服务。

在实际项目中,两者经常结合使用,各司其职,共同构建一个健壮的Web应用。

右滑查看面试常问