Spring MVC执行流程简介
Spring MVC 是一个基于 Java 的 Web 框架,其核心执行流程围绕 DispatcherServlet
(前端控制器)展开。以下是详细的分步执行流程,结合了请求处理的关键组件:
1. 请求接收:DispatcherServlet
拦截请求
- 所有 HTTP 请求首先被
DispatcherServlet
(在web.xml
或 Servlet 3.0+ 配置中定义)拦截。 - 作用:作为中央调度器,统一接收请求并协调后续流程。
2. 处理器映射:HandlerMapping
查找处理器
DispatcherServlet
查询HandlerMapping
组件。- 功能:根据请求 URL(如
/user/list
),找到对应的处理器(Controller 中的方法)。 - 示例:通过注解
@RequestMapping("/user/list")
映射到具体方法。
3. 处理器适配:HandlerAdapter
适配执行
- 获取处理器后,
DispatcherServlet
调用HandlerAdapter
。 - 作用:适配不同类型的处理器(如基于注解的
@Controller
或传统的Controller
接口),执行目标方法(如userController.list()
)。
4. 处理器执行:Controller 处理业务逻辑
HandlerAdapter
调用 Controller 方法。- 流程:
- 参数解析:
HandlerMethodArgumentResolver
解析请求参数(如@RequestParam
、@RequestBody
)。 - 业务处理:执行方法内的业务逻辑(如调用 Service 层)。
- 返回结果:返回
ModelAndView
(视图 + 数据)或String
(视图名),若用@ResponseBody
则返回数据对象。
- 参数解析:
5. 视图解析:ViewResolver
解析视图名
- 若返回的是视图名(如
"userList"
),DispatcherServlet
调用ViewResolver
。 - 功能:将逻辑视图名转换为实际视图对象(如 JSP
/WEB-INF/views/userList.jsp
或 Thymeleaf 模板)。
6. 视图渲染:View
渲染输出
- 获取
View
对象后,进行渲染:- 模型填充:将 Controller 返回的模型数据合并到视图中。
- 生成响应:生成 HTML/JSON/XML 等响应内容。
- 输出响应:通过
HttpServletResponse
返回给客户端。
7. 请求结束:返回响应
- 最终响应返回客户端,流程结束。
关键扩展点
-
拦截器 (
Interceptor
)- 在处理器执行前后插入逻辑(如权限验证)。
- 执行顺序:
preHandle()
→ Controller →postHandle()
→ 视图渲染 →afterCompletion()
。
-
参数解析器 (
HandlerMethodArgumentResolver
)- 解析 Controller 方法参数(如
@RequestParam
、@PathVariable
)。
- 解析 Controller 方法参数(如
-
返回值处理器 (
HandlerMethodReturnValueHandler
)- 处理
@ResponseBody
、Model
等返回值。
- 处理
-
异常处理 (
HandlerExceptionResolver
)- 统一处理 Controller 抛出的异常(如
@ExceptionHandler
)。
- 统一处理 Controller 抛出的异常(如
流程图概要
客户端请求↓
DispatcherServlet(拦截请求)↓
HandlerMapping(查找处理器)↓
HandlerAdapter(适配执行)↓
Controller(处理业务逻辑,返回结果)↓
ViewResolver(解析视图名)↓
View(渲染视图)↓
返回响应至客户端
注解驱动简化流程
现代 Spring MVC 大量使用注解简化开发:
@Controller
/@RestController
:声明处理器类。@RequestMapping
/@GetMapping
:映射请求路径。@ResponseBody
:直接返回 JSON/XML 数据(跳过视图解析)。
特点总结
- 松耦合:各组件职责单一(如
HandlerMapping
只负责映射)。 - 扩展性强:支持自定义
ViewResolver
、HandlerAdapter
等。 - 集成便捷:无缝整合 Spring IoC、AOP 等功能。
通过这一流程,Spring MVC 实现了灵活的请求处理机制,开发者只需关注业务逻辑,无需处理底层通信细节。