Spring Web网络请求执行流程
最近在梳理我的项目,回首发现很多基础的处理流程由框架接手,我甚至对自己的代码感到一些陌生,无法详细、基础的梳理数据的输入、处理、输出流程,于是我开始详细地复习和总结一些基础的知识,并尽量将其整理和流畅的描述
本文中我将梳理对Spring Web的理解,尽量详细、简洁、准确地描述其完整的处理流程。
将包括从 Tomcat 作为 Web 服务器接收请求,到 Spring MVC 中的控制器路由映射,再到 DispatcherServlet
的具体工作流程。
在 Spring Web(包括 Spring MVC 和 Spring Boot)中,控制器(Controller)层的路由映射是通过注解驱动的方式实现的。Spring MVC 会扫描带有特定注解的类和方法,自动将请求的 URL 映射到相应的控制器方法。
控制器路由映射实现原理
- Tomcat 的角色:
- 在 Spring Web 应用中,Tomcat 作为 Servlet 容器,负责接收 HTTP 请求并将请求传递给相应的
DispatcherServlet
。Tomcat 是整个请求处理流程的起点,但并不直接参与 Spring MVC 的路由映射。 - 它通过配置的
Connector
组件监听指定端口(例如 8080),接收到客户端请求后,将其交给适当的 Servlet 进行处理。在 Spring Boot 或 Spring MVC 应用中,这通常是DispatcherServlet
。
- 在 Spring Web 应用中,Tomcat 作为 Servlet 容器,负责接收 HTTP 请求并将请求传递给相应的
- 控制器类注解:
- 控制器类通常会使用
@Controller
或@RestController
注解标记。这些注解告诉 Spring MVC 这个类是一个控制器,并且应该被扫描。
- 控制器类通常会使用
- 请求映射注解:
- 控制器方法通常会使用
@RequestMapping
或它的派生注解,如@GetMapping
,@PostMapping
,@PutMapping
,@DeleteMapping
等来指定 HTTP 请求的方法和路径。这些注解定义了方法与 URL 的映射关系。
- 控制器方法通常会使用
- 扫描控制器类:
- Spring MVC 通过
@ComponentScan
或者@SpringBootApplication
注解来扫描控制器类。扫描过程中,Spring MVC 会找到所有标记为控制器的类,并将它们注册为 Spring Bean。
- Spring MVC 通过
- 请求分发:
- 当一个 HTTP 请求到达时,Tomcat 会将请求转发给 Spring MVC 的
DispatcherServlet
。DispatcherServlet
负责接收请求并进行进一步的处理。具体来说,它会根据请求 URL 和 HTTP 方法(GET、POST 等)选择合适的控制器方法进行调用。
- 当一个 HTTP 请求到达时,Tomcat 会将请求转发给 Spring MVC 的
- 请求映射解析:
- Spring MVC 使用
HandlerMapping
接口的实现类来解析请求 URL 并将其映射到控制器方法上。默认情况下,Spring MVC 使用RequestMappingHandlerMapping
来处理@RequestMapping
注解。 HandlerMapping
会查找与请求匹配的控制器方法,并将请求传递给该方法。
- Spring MVC 使用
- 参数绑定:
- Spring MVC 可以自动将请求参数绑定到控制器方法的参数上,通过使用
@RequestParam
,@PathVariable
,@RequestBody
,@ModelAttribute
等注解。通过这些注解,Spring MVC 会自动从请求中提取数据并将其绑定到控制器方法的参数上。
- Spring MVC 可以自动将请求参数绑定到控制器方法的参数上,通过使用
- 视图渲染:
- 控制器方法返回一个视图名称或模型视图对象。
DispatcherServlet
会将视图名称交给视图解析器来查找实际的视图,并渲染视图。
- 控制器方法返回一个视图名称或模型视图对象。
DispatcherServlet 解析
DispatcherServlet
是 Spring MVC 中的核心组件,负责处理所有的 HTTP 请求,并将请求分发到合适的控制器方法。它管理着整个请求-响应周期,确保请求的处理和响应的生成。
DispatcherServlet 作用
- 请求入口:
- 客户端发起的所有请求首先由
DispatcherServlet
接收,并转发给适当的处理器(控制器方法)。
- 客户端发起的所有请求首先由
- 请求分发:
DispatcherServlet
使用HandlerMapping
和HandlerAdapter
来选择合适的控制器方法,并绑定请求参数。
- 视图渲染:
- 执行完控制器方法后,
DispatcherServlet
选择并渲染视图,通过ViewResolver
解析视图名。
- 执行完控制器方法后,
- 拦截器支持:
DispatcherServlet
支持拦截器,可以在请求处理前后执行操作,如日志记录、权限验证等。
- 异常处理:
DispatcherServlet
处理控制器抛出的异常,并转换为适当的错误视图或错误响应。
DispatcherServlet 工作流程
- 请求到达:
- Web 服务器(如 Tomcat)接收 HTTP 请求并将其转发给
DispatcherServlet
。
- Web 服务器(如 Tomcat)接收 HTTP 请求并将其转发给
- 获取请求信息:
DispatcherServlet
从HttpServletRequest
获取请求方法、URL、参数等信息。
- 请求映射:
DispatcherServlet
通过HandlerMapping
解析请求 URL,找到匹配的控制器方法。
- 创建 HandlerExecutionChain:
- 通过
HandlerMapping
,找到控制器方法并创建HandlerExecutionChain
,它包含控制器方法和相关拦截器。
- 通过
- 调用控制器方法:
- 使用
HandlerAdapter
调用控制器方法,并将请求参数绑定到方法的参数上。
- 使用
- 视图渲染:
- 控制器返回视图或模型视图对象,
DispatcherServlet
使用ViewResolver
渲染视图。
- 控制器返回视图或模型视图对象,
- 响应生成:
- 最终,生成的响应通过
HttpServletResponse
发送回客户端。
- 最终,生成的响应通过
Tomcat 如何处理 HTTP 请求
Tomcat 作为 Web 服务器,处理 HTTP 请求的流程涉及多个步骤,主要通过 Connector
、Host
和 Context
组件来完成。
Tomcat 接收 HTTP 请求的流程
- 网络层:
- 客户端发起 HTTP 请求,通过网络传输到服务器。
- Connector 组件:
- Tomcat 的 Connector 组件负责监听指定端口并接收客户端的 HTTP 请求。它支持多种协议(如 HTTP/1.1、HTTPS、AJP)。
- Host 和 Context:
- Connector 接收到请求后,基于请求的主机名(Host header)和上下文路径(Context path),将请求分发给相应的
Host
和Context
组件。
- Connector 接收到请求后,基于请求的主机名(Host header)和上下文路径(Context path),将请求分发给相应的
- Web 应用容器:
- 请求分发给正确的
Context
后,Tomcat 的 Web 应用容器(Servlet 容器)处理请求。
- 请求分发给正确的
- Servlet 容器:
- Servlet 容器通过 URL 映射找到合适的 Servlet,并调用其
service()
方法来处理请求。
- Servlet 容器通过 URL 映射找到合适的 Servlet,并调用其
- DispatcherServlet(Spring MVC):
- 在 Spring MVC 应用中,
DispatcherServlet
负责接收请求并将其分发到控制器方法。
- 在 Spring MVC 应用中,
- 视图渲染和响应生成:
- 控制器方法执行后,
DispatcherServlet
通过视图解析器渲染视图,最终将响应发送回客户端。
- 控制器方法执行后,
Tomcat Connector 组件
- 配置 Connector:
- 在
server.xml
文件中配置Connector
,指定监听端口、协议类型等。
- 在
- 监听网络连接:
- Connector 监听指定端口,接收客户端连接并解析 HTTP 请求。
- 请求处理:
- Connector 会从线程池中分配线程,读取并解析 HTTP 请求,传递给后续组件处理。
- 响应发送:
- 一旦请求处理完毕,Connector 会将响应写回客户端,并管理连接状态。