OncePerRequestFilter的作用

196 阅读4分钟

顾名思义,每次请求时都会执行,OncePerRequestFilter类是Spring Boot框架中的内置功能。

OncePerRequestFilter简介

Filter 基类,旨在保证在任何 servlet 容器上每个请求分派执行一次。它提供了一个 doFilterInternal 带有 HttpServletRequest 和 HttpServletResponse 参数的方法。 从 Servlet 3.0 开始,过滤器可以作为 or REQUEST ASYNC 分派的一部分调用,这些分派发生在单独的线程中。可以配置web. xml过滤器是否应该参与异步分派。但是,在某些情况下,Servlet 容器采用不同的默认配置。因此,如果子类确实应该在两种类型的 dispatch 期间调用一次,以提供线程初始化、日志记录、安全性等,则可以覆盖该方法shouldNotFilterAsyncDispatch()以静态声明。此机制是对使用 Dispatcher 类型配置过滤器的补充,而不是取代 Dispatcher 类型。web. xml 子类可用于 isAsyncDispatch(HttpServletRequest) 确定何时作为异步分派的一部分调用过滤器,并用于 isAsyncStarted(HttpServletRequest) 确定何时将请求置于异步模式,因此当前分派不会是给定请求的最后一个分派。 另一个同样出现在其自身线程中的调度类型是 ERROR。如果子类希望静态声明,如果它们应该在错误分派期间调用一次,则可以覆盖shouldNotFilterErrorDispatch()。 该方法 getAlreadyFilteredAttributeName 确定如何识别请求是否已被筛选。默认实现基于具体过滤器实例的配置名称。

从上述看到OncePerRequestFilter的简介,那么文档中一直提到servlet容器,那么servlet容器是什么呢?

servlet容器属于tomcat中的,那么在常见的Springboot工程中都是内置tomcat的,所以在常见的代码中就不容易看到servlet这个关键字,但是servlet容器在请求和响应中是必不可少的,以下就是servlet的工作过程(实际上代码中@xxxMapping("/url")就是一个servlet地址):

1.客户端发送请求(HTTP 请求) :客户端(如浏览器)向服务器发送一个请求。
2.请求到达 Web 服务器(Servlet 容器) :Web 服务器(如 Tomcat)接收并解析 HTTP 请求,找出对应的 Servlet。
3.Servlet 容器选择相应的 ServletServlet 容器通过请求 URL、请求映射(web.xml 配置文件或者注解)来确定哪个 Servlet 来处理该请求。
4.Servlet 容器初始化 Servlet如果是第一次请求该 Servlet,容器会创建一个 Servlet 实例并初始化它(调用 init() 方法)。
5.Servlet 处理请求:容器将请求封装为 HttpServletRequest 对象,响应封装为 HttpServletResponse 对象,传递给对应的 Servlet。Servlet 通过 doGet()doPost() 等方法来处理请求。
6.Servlet 返回响应:Servlet 通过 HttpServletResponse 对象将响应内容(如 HTML、JSON、XML 等)返回给客户端。
7.客户端接收响应:客户端浏览器收到响应并呈现给用户。

+---------------------+          +-------------------------------+
|     客户端          |   --->   |       Web 服务器 (Servlet 容器)|
|    (浏览器/应用)    |          |    (如 Tomcat, Jetty等)        |
+---------------------+          +-------------------------------+
          |                                   |
          | HTTP 请求 (Request)                |
          v                                   v
+---------------------+        +----------------------------------+
|      请求解析       | ---->  | 确定匹配的 Servlet                |
|    (Web 服务器)    |        | 根据请求 URL 或映射来定位 Servlet|
+---------------------+        +----------------------------------+
          |                                   |
          | 找到 Servlet                       |
          v                                   v
+---------------------+        +----------------------------------+
|  Servlet 初始化    |        | 通过 web.xml 或 注解找到        |
|   (调用 init() 方法) |        | 对应的 Servlet 类               |
+---------------------+        +----------------------------------+
          |                                   |
          | 将请求封装为 `HttpServletRequest`   |
          v                                   v
+---------------------+        +----------------------------------+
|    Servlet 处理请求 | ----> | Servlet 通过 doGet() / doPost() |
| (调用 `doGet` / `doPost`) |    | 处理请求并生成响应              |
+---------------------+        +----------------------------------+
          |                                   |
          | 响应结果封装为 `HttpServletResponse`|
          v                                   v
+---------------------+        +----------------------------------+
|     返回响应       |        | Servlet 返回响应给客户端        |
|  (如 HTML, JSON)   |        | (通过 `response.getWriter()`)  |
+---------------------+        +----------------------------------+
          |                                   |
          | HTTP 响应 (Response)               |
          v                                   v
+---------------------+          +-------------------------------+
|   客户端接收响应    | <---     |        Web 服务器              |
|   (浏览器呈现内容)  |          |       (Servlet 容器)           |
+---------------------+          +-------------------------------+

了解完servlet后看下OncePerRequestFilter是在什么时机触发的
  • 请求到达 Servlet 容器(如 Tomcat)

    • 请求首先进入 Servlet 容器。
  • 过滤器链(包括 OncePerRequestFilter)执行

    • 请求会经过一系列配置的过滤器,首先经过 OncePerRequestFilter
    • 在这里,可以进行请求预处理、日志记录、安全性检查等操作。
  • Servlet 执行请求处理逻辑

    • 请求经过过滤器后,最终会到达目标 Servlet(如 Spring 的 Controller 或普通 Servlet),由它来处理业务逻辑并生成响应。
  • 响应通过过滤器链返回

    • 处理完请求后,生成的响应会经过过滤器链返回,OncePerRequestFilter 会在这个阶段进行响应的后处理操作。
  • 返回响应给客户端

+---------------------+          +-------------------------------+
|     客户端          |   --->   |       Web 服务器 (Servlet 容器)|
|    (浏览器/应用)    |          |    (如 Tomcat, Jetty等)        |
+---------------------+          +-------------------------------+
          |                                   |
          | HTTP 请求 (Request)                |
          v                                   v
+---------------------+        +----------------------------------+
|      请求解析       | ---->  | 确定匹配的 Servlet                |
|    (Web 服务器)    |        | 根据请求 URL 或映射来定位 Servlet|
+---------------------+        +----------------------------------+
          |                                   |
          | 找到 Servlet                       |
          v                                   v
+---------------------+        +----------------------------------+
|  Servlet 初始化    |        | 通过 web.xml 或 注解找到        |
|   (调用 init() 方法) |        | 对应的 Servlet 类               |
+---------------------+        +----------------------------------+
          |                                   |
          | 将请求封装为 `HttpServletRequest`   |
          v                                   v
+---------------------+        +----------------------------------+
|    请求进入过滤器链 | ---->  | 过滤器执行(如 OncePerRequestFilter)|
| (如 OncePerRequestFilter)  |     | 过滤器对请求/响应进行处理       |
+---------------------+        +----------------------------------+
          |                                   |
          | 请求继续传递给目标 Servlet       |
          v                                   v
+---------------------+        +----------------------------------+
|    Servlet 处理请求 | ----> | Servlet 通过 doGet() / doPost() |
| (调用 `doGet` / `doPost`) |    | 处理请求并生成响应              |
+---------------------+        +----------------------------------+
          |                                   |
          | 响应结果封装为 `HttpServletResponse`|
          v                                   v
+---------------------+        +----------------------------------+
|     返回响应       |        | Servlet 返回响应给客户端        |
|  (如 HTML, JSON)   |        | (通过 `response.getWriter()`)  |
+---------------------+        +----------------------------------+
          |                                   |
          | HTTP 响应 (Response)               |
          v                                   v
+---------------------+          +-------------------------------+
|   客户端接收响应    | <---     |        Web 服务器              |
|   (浏览器呈现内容)  |          |       (Servlet 容器)           |
+---------------------+          +-------------------------------+