顾名思义,每次请求时都会执行,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 容器) |
+---------------------+ +-------------------------------+