Spring MVC 核心流程与配置详解:从请求到响应的完整链路
Spring MVC 是基于 MVC 设计模式的 Web 框架,其核心是通过 DispatcherServlet(前端控制器) 统一调度所有请求,配合 HandlerMapping、HandlerAdapter、ViewResolver 等组件完成 “请求处理→业务逻辑→视图渲染” 的全流程。,从 “执行流程拆解→核心组件职责→Java 配置方式” 三个维度,彻底讲透 Spring MVC 的工作原理。
Spring MVC 核心执行流程(图文解析)
Spring MVC 的执行流程围绕 DispatcherServlet 展开,共 8 个关键步骤,每个步骤由特定组件协作完成,确保请求按规范流转:
步骤 1:用户发送请求,DispatcherServlet 接收请求
- 触发点:用户通过浏览器 / 客户端发送 HTTP 请求(如
GET /user/list),请求首先到达 Web 容器(如 Tomcat); - DispatcherServlet 角色:作为 Spring MVC 的 “前端控制器”,是所有请求的统一入口,负责全局流程控制,自身不处理具体业务逻辑;
- 底层机制:Web 容器通过
web.xml或 Java 配置,将所有请求(或指定 URL 模式)映射到 DispatcherServlet(如配置url-pattern: /拦截所有请求)。
步骤 2:DispatcherServlet 调用 HandlerMapping,获取 HandlerExecutionChain
- HandlerMapping 职责:根据请求 URL 找到对应的 “处理器(Handler,通常是 Controller 的方法)”,并返回
HandlerExecutionChain对象; - HandlerExecutionChain 组成:包含两部分:
- Handler:具体的业务处理器(如
UserController的getUserList()方法); - HandlerInterceptor 数组:请求处理前后的拦截器(如日志拦截器、权限拦截器);
- Handler:具体的业务处理器(如
- 核心设计模式:策略模式。Spring 提供多种 HandlerMapping 实现(如
RequestMappingHandlerMapping用于注解式 Controller),可灵活切换映射策略(如按 URL 路径、按请求参数映射)。
示例:当请求 URL 为 /user/list 时,RequestMappingHandlerMapping 会匹配 @Controller 类中 @RequestMapping("/user/list") 注解的方法,将其作为 Handler 封装到 HandlerExecutionChain 中。
步骤 3:DispatcherServlet 调用 HandlerAdapter,适配 Handler
- HandlerAdapter 职责:作为 “适配器”,将 Handler 适配为 DispatcherServlet 可调用的形式,解决 “DispatcherServlet 如何调用不同类型 Handler” 的问题;
- 核心设计模式:适配器模式。Spring 支持多种 Handler 类型(如注解式 Controller、实现
Controller接口的类),每种 Handler 对应一种 HandlerAdapter(如RequestMappingHandlerAdapter适配注解式 Controller); - 关键作用:
- 参数绑定:将请求参数(如 URL 路径参数、表单参数)转换为 Handler 方法的参数(如
@RequestParam String username); - 数据转换:处理参数类型转换(如 String 转 Integer、JSON 字符串转 Java 对象);
- 方法调用:调用适配后的 Handler 方法,执行业务逻辑。
- 参数绑定:将请求参数(如 URL 路径参数、表单参数)转换为 Handler 方法的参数(如
步骤 4:HandlerAdapter 调用 Handler,执行业务逻辑并返回 ModelAndView
- 业务逻辑执行:HandlerAdapter 调用 Handler 的具体方法(如
UserController.getUserList()),执行数据库查询、业务计算等逻辑; - 参数绑定细节:HandlerAdapter 会通过WebDataBinder完成以下工作:
- 解析请求参数(从 URL、请求头、请求体中提取参数);
- 类型转换(如将请求中的字符串 “2024” 转换为 Integer 2024);
- 数据校验(如通过
@Valid注解校验参数合法性);
- 返回结果:Handler 执行完成后,返回ModelAndView对象,包含两部分信息:
- Model:业务数据(本质是
Map<String, Object>,如用户列表model.put("userList", userList)); - View:逻辑视图名(如
"user/list",仅表示视图的 “逻辑名称”,而非具体页面路径)。
- Model:业务数据(本质是
特殊情况:若 Handler 方法返回 @ResponseBody 注解(如 RESTful 接口),则不会返回 ModelAndView,而是直接将业务数据转换为 JSON/XML 等格式,跳过后续视图渲染步骤。
步骤 5:DispatcherServlet 调用 ViewResolver,解析 View
ViewResolver 职责:将
ModelAndView中的 “逻辑视图名” 解析为 “具体的 View 对象”(如 JSP 页面、Thymeleaf 模板);核心设计模式:策略模式
。Spring 提供多种 ViewResolver 实现,支持不同视图技术:
| ViewResolver 实现类 | 支持的视图技术 | 逻辑视图名解析示例 |
| —————————————— | ———————- | ——————————————————————————- |
| InternalResourceViewResolver | JSP |"user/list"→/WEB-INF/views/user/list.jsp|
| ThymeleafViewResolver | Thymeleaf 模板 |"user/list"→classpath:/templates/user/list.html|
| FreeMarkerViewResolver | FreeMarker 模板 |"user/list"→/WEB-INF/views/user/list.ftl|解析逻辑:ViewResolver 根据配置的 “前缀” 和 “后缀” 拼接逻辑视图名,生成具体的视图路径,再创建对应的 View 对象(如
InternalResourceView对应 JSP)。
步骤 6:View 渲染,将 Model 数据填充到视图
- View 职责:将 Model 中的业务数据渲染到具体视图(如 JSP、HTML),生成最终的 HTML 响应;
- 渲染过程:
- View 对象接收 Model 中的
Map数据; - 根据视图技术的语法(如 JSP 的 EL 表达式
${userList}、Thymeleaf 的th:each="user : ${userList}"),将数据填充到视图模板中; - 生成完整的 HTML 文档,作为响应体返回给 DispatcherServlet。
- View 对象接收 Model 中的
步骤 7:DispatcherServlet 返回响应给用户
- 响应流转:View 渲染完成后,将 HTML 响应返回给 DispatcherServlet,再由 DispatcherServlet 通过 Web 容器将响应发送给用户浏览器;
- 流程结束:至此,整个请求 - 响应流程完成,DispatcherServlet 等待下一次请求。
核心流程总结(简化版)
Spring MVC 核心组件职责梳理
| 组件名称 | 核心职责 | 关键设计模式 | 常用实现类 |
|---|---|---|---|
| DispatcherServlet | 前端控制器,统一请求入口,调度其他组件 | 前端控制器模式 | DispatcherServlet(唯一实现) |
| HandlerMapping | 根据 URL 映射到 Handler 及拦截器 | 策略模式 | RequestMappingHandlerMapping |
| HandlerAdapter | 适配 Handler,处理参数绑定并调用方法 | 适配器模式 | RequestMappingHandlerAdapter |
| Handler(处理器) | 执行业务逻辑,返回 ModelAndView 或 JSON | 无(业务组件) | 注解式 Controller(@Controller) |
| ModelAndView | 封装业务数据(Model)和逻辑视图名(View) | 无(数据载体) | ModelAndView |
| ViewResolver | 将逻辑视图名解析为具体 View 对象 | 策略模式 | InternalResourceViewResolver |
| View(视图) | 渲染 Model 数据到视图模板 | 策略模式 | InternalResourceView(JSP)、ThymeleafView |
| HandlerInterceptor | 请求处理前后的拦截(日志、权限等) | 拦截器模式 | HandlerInterceptorAdapter |
Spring 3.2+ 新功能:Java 配置方式(替代 web.xml)
在 Spring 3.2 之前,Spring MVC 的配置依赖 web.xml(如配置 DispatcherServlet、监听器)。Spring 3.2 引入 AbstractDispatcherServletInitializer 抽象类,支持纯 Java 代码配置,无需任何 XML 文件,简化了 Web 应用的初始化流程。
1. 核心抽象类:AbstractDispatcherServletInitializer
该类实现了 Servlet 3.0+ 的 WebApplicationInitializer 接口,Web 容器(如 Tomcat 7+)会自动检测并执行其 onStartup() 方法,完成 DispatcherServlet 的注册和配置。
关键方法(需子类重写)
| 方法名 | 作用 | 示例实现 |
|---|---|---|
createServletApplicationContext() |
创建 DispatcherServlet 对应的 Spring 容器(Web 容器),扫描 Controller、HandlerMapping 等组件 | 返回 AnnotationConfigWebApplicationContext,注册配置类 |
getServletMappings() |
配置 DispatcherServlet 拦截的 URL 模式 | 返回 new String[]{"/"}(拦截所有请求) |
createRootApplicationContext() |
创建根 Spring 容器(可选),扫描 Service、Dao 等非 Web 组件 | 返回 AnnotationConfigWebApplicationContext,注册根配置类 |
2. 注解式配置子类:AbstractAnnotationConfigDispatcherServletInitializer
Spring 进一步提供 AbstractAnnotationConfigDispatcherServletInitializer 子类,专门用于 基于注解的 Java 配置,无需手动创建 ApplicationContext,只需指定配置类即可。
完整示例:Java 配置 Spring MVC
1 | import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; |
3. Java 配置 vs web.xml 配置
| 配置方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Java 配置(推荐) | 类型安全、无 XML 依赖、易于重构 | 需熟悉 Spring 注解和抽象类 | Spring 3.2+、Servlet 3.0+ 环境 |
| web.xml 配置(传统) | 直观易懂、适合老项目迁移 | 类型不安全、XML 冗余、不易维护 | 老项目、低版本 Servlet 环境 |
关键补充:静态资源处理
当 DispatcherServlet 配置为拦截所有请求(url-pattern: /)时,会导致静态资源(如 CSS、JS、图片)也被拦截,无法正常访问。需在 Web 配置类中添加静态资源映射:
1 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; |
总结
Spring MVC 的核心是 “前端控制器 + 组件协作”,通过 DispatcherServlet 统一调度,配合 HandlerMapping、HandlerAdapter、ViewResolver 等组件,实现请求的高效处理和灵活扩展。Spring 3.2+ 引入的 Java 配置方式(AbstractAnnotationConfigDispatcherServletInitializer)进一步简化了配置流程,替代了传统的 web.xml,是现代 Spring MVC 项目的推荐配置方式

v1.3.10