过滤器 & 拦截器

119 阅读6分钟

在 Java 中,过滤器(Filter)和拦截器(Interceptor)有一定的关联,但也存在一些区别。

一、关联

  1. 目的相似

    • 过滤器和拦截器都是为了对请求进行预处理和后处理,实现一些通用的功能,如日志记录、权限验证、字符编码设置等。它们可以在请求到达目标资源之前或响应返回给客户端之后进行操作,从而增强系统的可维护性和可扩展性。
  2. 作用于请求处理流程

    • 两者都可以介入到 Web 应用的请求处理流程中,对请求和响应进行干预。它们可以在请求被处理之前或之后执行特定的逻辑,从而实现对请求的过滤和拦截。

二、区别

  1. 实现方式

    • 过滤器是基于 Servlet 规范实现的,它是由 Servlet 容器管理的。过滤器通过实现javax.servlet.Filter接口,并在web.xml文件中进行配置,或者使用注解进行配置,来定义对请求的过滤逻辑。
    • 拦截器是基于 Spring 框架实现的,它是由 Spring 容器管理的。拦截器通过实现org.springframework.web.servlet.HandlerInterceptor接口,并在 Spring 的配置文件中进行配置,来定义对请求的拦截逻辑。
  2. 作用范围

    • 过滤器可以作用于所有的请求,包括静态资源(如图片、CSS 文件、JavaScript 文件等)和动态资源(如 Servlet、JSP 页面等)。过滤器可以对请求进行全局的过滤,例如设置字符编码、压缩响应等。
    • 拦截器主要作用于 Spring 管理的控制器方法的请求。拦截器可以对特定的请求进行拦截,例如进行权限验证、日志记录等。拦截器可以更加精细地控制对请求的处理。
  3. 执行顺序

    • 过滤器的执行顺序是在请求到达 Servlet 之前和响应返回给客户端之后。多个过滤器可以按照它们在web.xml文件中的配置顺序依次执行。
    • 拦截器的执行顺序是在请求到达控制器方法之前和响应返回给客户端之后。多个拦截器可以按照它们在 Spring 配置文件中的配置顺序依次执行。拦截器还可以通过实现org.springframework.core.Ordered接口或使用@Order注解来指定执行顺序。
  4. 与业务逻辑的耦合度

    • 过滤器与业务逻辑的耦合度较低,它主要关注对请求和响应的通用处理,不涉及具体的业务逻辑。过滤器可以在不修改业务代码的情况下,对请求进行过滤和处理。

    • 拦截器与业务逻辑的耦合度相对较高,它可以在请求到达控制器方法之前和之后执行一些与业务相关的逻辑,例如权限验证、日志记录等。拦截器可以通过获取请求和响应的信息,与业务逻辑进行交互。

三、适用场景

综上所述,过滤器和拦截器在 Java Web 应用中都有各自的用途。过滤器适用于对所有请求进行全局的过滤和处理,而拦截器适用于对 Spring 管理的控制器方法的请求进行拦截和处理。 在实际应用中,可以根据具体的需求选择使用过滤器或拦截器,或者两者结合使用,以实现更加灵活和强大的请求处理功能。

四、项目中同时存在过滤器和拦截器,先执行哪个?

如果项目中同时存在过滤器和拦截器,会先执行过滤器。

原因如下:

一、执行机制角度

过滤器是由 Servlet 容器(如Tomcat)管理的,在请求到达 Servlet 之前就开始发挥作用。 当一个请求进入 Web 应用时,Servlet 容器会首先根据配置检查是否有过滤器需要应用于该请求。如果有,就按照过滤器的配置顺序依次执行过滤器的逻辑。而拦截器是由 Spring 框架管理的,Spring 框架是建立在 Servlet 规范之上的应用框架。在请求经过 Servlet 容器的初步处理后,才会进入到 Spring 框架的处理流程中,此时才会触发拦截器的执行。

二、请求处理流程角度

请求的处理流程是先经过 Servlet 容器的一系列处理,包括过滤器的过滤。过滤器可以对所有的请求进行全局的处理,包括静态资源和动态资源的请求。而拦截器主要针对 Spring 管理的控制器方法的请求进行拦截处理。所以在请求到达特定的业务逻辑(由 Spring 管理的控制器方法)之前,先经过 Servlet 容器的过滤器处理。

综上所述,由于过滤器在 Servlet 容器层面先于 Spring 框架的拦截器发挥作用,所以项目中同时存在过滤器和拦截器时会先执行过滤器。

五、为什么还需要拦截器?

虽然过滤器和拦截器在某些功能上有相似之处,但 Spring 框架引入拦截器有其特定的原因,并非过滤器功能更全面就无需拦截器了。

一、过滤器的局限性

  1. 作用范围较宽泛

    • 过滤器可以作用于所有请求,包括静态资源等,但有时候我们只希望针对特定的业务逻辑进行处理,比如只对 Spring 管理的控制器方法进行干预,过滤器无法做到如此精细的控制。
  2. 与 Spring 框架结合不紧密

    • 过滤器是 Servlet 规范的一部分,与 Spring 框架的结合相对松散。在处理一些需要深度结合 Spring 特性的场景时,可能会比较麻烦。例如,在过滤器中获取 Spring 管理的 Bean 可能需要一些额外的操作,不如拦截器方便。

二、拦截器的优势

  1. 更贴近业务逻辑

    • 拦截器可以专门针对 Spring 管理的控制器方法进行拦截,能够更好地满足业务需求。比如在权限验证方面,可以根据 Spring Security 等框架提供的用户认证信息进行更精细的权限控制。
  2. 与 Spring 框架深度集成

    • 拦截器由 Spring 容器管理,可以方便地与 Spring 的其他功能进行集成。例如,可以轻松地利用 Spring 的依赖注入机制,将所需的服务注入到拦截器中,以便在拦截过程中使用。

    我觉得这个才是最重要的,因为毕竟拦截器是依赖于spring容器的,但是过滤器又是servlet规范的产物,他们之间的适配性肯定不如spring自己写的拦截器来的方便。

  3. 灵活性高

    • 通过实现不同的拦截器接口,可以实现多种类型的拦截逻辑。同时,可以通过配置拦截器的执行顺序,更加灵活地控制请求的处理流程。

六、总结

  1. 过滤器和拦截器的异同点。
  2. 过滤器和拦截器的使用场景。
  3. 同时存在的话,先执行哪个。
  4. 既然过滤器功能那么全面,为什么还需要拦截器的原因。(偏主观理解