过滤器和拦截器有什么区别?

过滤器和拦截器有什么区别?

在 Web 开发中,过滤器(Filter)和拦截器(Interceptor)是两个常用的组件,它们都能对请求进行预处理和后处理。但很多开发者对两者的区别存在疑惑,本文将从技术实现、应用场景、核心特性等多个维度深入解析二者的差异。

一、定义与核心作用对比

1. 过滤器(Filter)

  • 技术定位:Servlet 规范的原生组件,基于 Java EE 标准,所有支持 Servlet 的容器(如 Tomcat、Jetty)都内置支持

  • 核心接口:实现javax.servlet.Filter接口,包含三个核心方法:

init(FilterConfig config)  // 初始化方法
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)  // 核心处理方法
destroy()  // 销毁方法
  • 核心作用:对请求 / 响应进行链式过滤处理,主要用于处理与 Servlet 生命周期相关的通用功能,如:

  • 请求参数编码处理(CharacterEncodingFilter)

  • 权限验证(登录状态检查)

  • 响应数据压缩(GZipFilter)

  • 敏感词过滤

  • 跨域请求处理(CORSFilter)

2. 拦截器(Interceptor)

  • 技术定位:Spring MVC 框架特有的组件,基于 Spring 生态的 AOP 思想实现

  • 核心接口:实现org.springframework.web.servlet.HandlerInterceptor接口,包含三个核心方法:

preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  // 控制器方法执行前调用
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  // 控制器方法执行后调用
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)  // 整个请求完成后调用(包括视图渲染完成)
  • 核心作用:对控制器(Controller)的访问进行精细化拦截控制,主要用于处理与业务逻辑更相关的功能,如:

  • 接口访问频率限制

  • 方法级权限校验

  • 性能监控(计算接口响应时间)

  • 请求参数预处理(如数据格式转换)

  • 响应结果后处理(如添加统一响应头)

二、应用场景与触发时机差异

1. 执行流程对比

阶段 过滤器(Filter) 拦截器(Interceptor)
请求进入 最先触发,在 Servlet 容器接收请求后立即执行 在 DispatcherServlet 解析处理器映射之后触发
控制器调用前 属于 FilterChain 的一部分,按注册顺序执行 preHandle () 方法在此阶段执行
控制器调用后 - postHandle () 方法在此阶段执行(视图渲染前)
响应返回前 属于 FilterChain 的一部分,按逆序执行 afterCompletion () 方法在此阶段执行(视图渲染后)
请求结束 最后执行(FilterChain 执行完毕后) 最后执行(整个请求处理流程结束后)

2. 典型应用场景

  • 过滤器更适合处理

  • 与 Servlet 规范强相关的底层处理(如请求体解析、响应流包装)

  • 需要在整个 Web 应用范围生效的通用功能

  • 对性能要求极高的场景(原生 Servlet 实现,轻量高效)

  • 拦截器更适合处理

  • Spring MVC 框架内的控制器级别的拦截(支持对 @Controller 和 @GetMapping 等注解的识别)

  • 需要访问 Spring 上下文(如注入 Service 组件)的业务逻辑处理

  • 支持细粒度的路径匹配(可配置只拦截特定的 URL 模式)

三、实现原理与技术架构对比

1. 底层实现机制

  • 过滤器实现原理
  1. Servlet 容器启动时加载 Filter 配置,创建 Filter 实例并调用 init () 初始化

  2. 每个请求到达时,容器创建 FilterChain 对象,按注册顺序依次调用 doFilter () 方法

  3. 调用 chain.doFilter () 会传递到下一个 Filter 或目标 Servlet

  4. 响应返回时按相反顺序执行后续过滤逻辑

  • 拦截器实现原理
  1. Spring MVC 启动时,通过 InterceptorRegistry 注册拦截器(可通过 WebMvcConfigurer 配置)

  2. DispatcherServlet 在处理请求时,先获取 HandlerExecutionChain(包含处理器和拦截器列表)

  3. 按顺序调用拦截器的 preHandle (),全部返回 true 才会执行控制器方法

  4. 控制器执行完毕后,按逆序调用 postHandle ()

  5. 视图渲染完成后,调用 afterCompletion ()

2. 注册方式对比

  • 过滤器注册(三种方式):

  • web.xml 配置:

<filter>
    <filter-name>encodingFilterfilter-name>
    <filter-class>com.example.EncodingFilterfilter-class>
filter>
<filter-mapping>
    <filter-name>encodingFilterfilter-name>
    <url-pattern>/*url-pattern>
filter-mapping>
  • @WebFilter 注解(Servlet 3.0+):
@WebFilter(urlPatterns = "/*", filterName = "encodingFilter")
public class EncodingFilter implements Filter { ... }
  • Spring Boot 中通过 FilterRegistrationBean 注册:
@Bean
public FilterRegistrationBean<EncodingFilter> encodingFilterRegistration() {
    FilterRegistrationBean<EncodingFilter> bean = new FilterRegistrationBean<>();
    bean.setFilter(new EncodingFilter());
    bean.addUrlPatterns("/*");
    return bean;
}
  • 拦截器注册(Spring MVC 方式):
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/api/**")  // 拦截路径
                .excludePathPatterns("/api/public/**");  // 排除路径
    }
}

四、功能粒度与灵活性对比

1. 处理对象差异

  • 过滤器:处理的是ServletRequest和ServletResponse的原始对象,只能在 Servlet 规范定义的接口范围内操作,无法直接访问 Spring Bean 或控制器方法细节

  • 拦截器:可以访问HttpServletRequest和HttpServletResponse,还能获取:

  • 处理器对象(handler,可能是 Controller 方法、静态资源等)

  • ModelAndView 对象(在 postHandle 阶段)

  • 异常信息(在 afterCompletion 阶段)

  • 支持直接注入 Spring Bean(通过 @Autowired)

2. 控制能力对比

特性 过滤器 拦截器
路径匹配粒度 基于 URL 模式(如 /、/api/ 支持 Ant 风格路径(如 /user/**)和正则表达式
条件判断支持 有限(主要依赖 URL 匹配) 强大(可在 preHandle 中编写复杂逻辑)
对异步请求的支持 部分支持(需特殊处理异步流程) 完全支持(Spring MVC 原生支持异步处理)
访问响应结果 只能通过 ServletResponse 操作 可通过 ModelAndView 修改视图数据
终止请求能力 通过不调用 chain.doFilter () 终止 通过 preHandle 返回 false 终止

3. 典型功能实现对比

  • 实现请求日志记录

  • 过滤器实现:在 doFilter 中记录请求 URL、时间戳,无法获取控制器方法名

  • 拦截器实现:在 preHandle 中通过 handler 获取具体的 Controller 方法(需转换为 HandlerMethod),可记录方法名、参数等详细信息

五、使用范围与框架相关性

1. 技术栈依赖性

  • 过滤器

  • 属于 Java EE 标准,不依赖任何框架,可在纯 Servlet 环境中使用

  • 支持所有符合 Servlet 规范的容器(从 Servlet 2.3 到最新的 5.0 版本)

  • 可与任何 Web 框架(Struts2、Spring MVC、Jakarta EE 等)配合使用

  • 拦截器

  • 是 Spring MVC 特有的组件,必须运行在 Spring 生态环境中

  • 依赖 Spring 框架的上下文环境,无法在纯 Servlet 或其他框架(如 Jakarta EE 原生 API)中使用

  • 深度集成 Spring MVC 的处理器映射(HandlerMapping)和视图解析流程

2. 执行顺序规则

  • 过滤器顺序

  • 由注册顺序决定(web.xml 中的顺序或 @WebFilter 的 order 属性)

  • 多个过滤器形成严格的链式结构,执行顺序不可逆

  • 拦截器顺序

  • 由 addInterceptors 方法中的注册顺序决定(先注册的先执行 preHandle,后注册的先执行 postHandle)

  • 支持多个拦截器的组合使用,形成责任链模式

六、如何选择使用过滤器还是拦截器?

1. 功能层级决策

  • 选择过滤器的场景

  • 需要处理最底层的请求 / 响应数据(如修改请求头、响应体)

  • 功能需要在整个 Web 应用范围生效(包括静态资源、错误页面等)

  • 希望兼容非 Spring 环境(如纯 Servlet 项目)

  • 对性能有极高要求(原生实现通常比框架组件更快)

  • 选择拦截器的场景

  • 需要针对控制器方法进行精细化拦截(如只拦截 @RestController 标注的接口)

  • 业务逻辑需要访问 Spring Bean(如调用 Service 进行权限校验)

  • 需要处理控制器方法的返回结果(修改 ModelAndView)

  • 需要使用更灵活的路径匹配规则(支持排除路径、正则表达式)

2. 最佳实践

  • 组合使用:在实际项目中,过滤器和拦截器通常配合使用,例如:
  1. 过滤器处理编码、跨域等底层通用功能

  2. 拦截器处理接口权限、性能监控等业务相关功能

  • 性能优化:对于不需要访问 Spring 上下文的通用功能,优先使用过滤器以减少框架层开销

  • 复杂逻辑处理:涉及业务逻辑或需要操作 ModelAndView 时,必须使用拦截器

总结

过滤器和拦截器虽然都是请求处理组件,但在技术定位、实现原理和应用场景上有明显区别:

对比维度 过滤器(Filter) 拦截器(Interceptor)
技术规范 Servlet 规范(Java EE 标准) Spring MVC 框架专属
核心接口 javax.servlet.Filter org.springframework.web.servlet.HandlerInterceptor
作用范围 整个 Web 应用(包括静态资源) Spring MVC 控制器级别
处理对象 ServletRequest/Response 原始对象 包含处理器细节的 HttpServletRequest/Response
框架依赖 无(纯 Java EE) 依赖 Spring 框架
典型应用 编码处理、权限校验、日志记录 方法级拦截、性能监控、数据预处理
注册方式 web.xml/@WebFilter/FilterRegistrationBean WebMvcConfigurer.addInterceptors()

理解两者的差异后,开发者可以根据具体需求选择合适的组件:过滤器适合处理底层通用功能,拦截器适合处理与 Spring MVC 深度整合的业务逻辑。在复杂项目中,二者通常协同工作,共同构建高效的请求处理流程。

你可能感兴趣的:(Java,java,springmvc,过滤器,拦截器)