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的Request和Response |
可以访问Spring上下文、Bean、Controller的Handler和ModelAndView |
| 控制粒度 (Granularity) | 粗粒度,基于URL模式(url-pattern) |
细粒度,可针对特定Handler(Controller) |
| 实现方式 (Implementation) | 实现javax.servlet.Filter接口 |
实现org.springframework.web.servlet.HandlerInterceptor接口 |
详细解释
1. 来源和依赖不同 (Origin & Dependency)
Filter (过滤器):
- 来源:
Filter是Java Servlet规范的一部分,定义在javax.servlet.Filter接口中。它不是Spring特有的功能,任何遵循Servlet规范的Web容器(如Tomcat、Jetty)都支持它。 - 依赖:它由Servlet容器管理,不依赖于Spring容器。因此,在
Filter中你无法直接注入Spring管理的Bean(如Service、Repository)。
- 来源:
Interceptor (拦截器):
- 来源:
Interceptor是Spring 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的请求,提供了更精细的控制点:preHandle: 在Controller方法执行之前调用。可以用于权限检查、日志记录等。如果返回false,则请求处理将在此中断。postHandle: 在Controller方法执行之后,但在视图(View)渲染之前调用。可以用于修改ModelAndView对象,向视图添加公共数据。afterCompletion: 在整个请求完成(包括视图渲染)之后调用。主要用于资源清理工作,无论是否发生异常都会执行。
- 拦截范围:它只拦截通过
DispatcherServlet分发的请求。对于静态资源(如果配置为不通过DispatcherServlet)或者直接访问其他Servlet的请求,Interceptor是无能为力的。
- 执行时机:
3. 可访问的资源和功能粒度不同 (Access & Granularity)
Filter (过滤器):
- 功能:
Filter可以获取原始的HttpServletRequest和HttpServletResponse对象。这意味着它可以修改请求的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应用。