0%

springmvc核心流程

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 组成:包含两部分:
    1. Handler:具体的业务处理器(如 UserControllergetUserList() 方法);
    2. HandlerInterceptor 数组:请求处理前后的拦截器(如日志拦截器、权限拦截器);
  • 核心设计模式策略模式。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);
  • 关键作用:
    1. 参数绑定:将请求参数(如 URL 路径参数、表单参数)转换为 Handler 方法的参数(如 @RequestParam String username);
    2. 数据转换:处理参数类型转换(如 String 转 Integer、JSON 字符串转 Java 对象);
    3. 方法调用:调用适配后的 Handler 方法,执行业务逻辑。

步骤 4:HandlerAdapter 调用 Handler,执行业务逻辑并返回 ModelAndView

  • 业务逻辑执行:HandlerAdapter 调用 Handler 的具体方法(如 UserController.getUserList()),执行数据库查询、业务计算等逻辑;
  • 参数绑定细节:HandlerAdapter 会通过WebDataBinder完成以下工作:
    • 解析请求参数(从 URL、请求头、请求体中提取参数);
    • 类型转换(如将请求中的字符串 “2024” 转换为 Integer 2024);
    • 数据校验(如通过 @Valid 注解校验参数合法性);
  • 返回结果:Handler 执行完成后,返回ModelAndView对象,包含两部分信息:
    1. Model:业务数据(本质是 Map<String, Object>,如用户列表 model.put("userList", userList));
    2. View:逻辑视图名(如 "user/list",仅表示视图的 “逻辑名称”,而非具体页面路径)。

特殊情况:若 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 响应;
  • 渲染过程:
    1. View 对象接收 Model 中的 Map 数据;
    2. 根据视图技术的语法(如 JSP 的 EL 表达式 ${userList}、Thymeleaf 的 th:each="user : ${userList}"),将数据填充到视图模板中;
    3. 生成完整的 HTML 文档,作为响应体返回给 DispatcherServlet。

步骤 7:DispatcherServlet 返回响应给用户

  • 响应流转:View 渲染完成后,将 HTML 响应返回给 DispatcherServlet,再由 DispatcherServlet 通过 Web 容器将响应发送给用户浏览器;
  • 流程结束:至此,整个请求 - 响应流程完成,DispatcherServlet 等待下一次请求。

核心流程总结(简化版)

graph TD
    A[用户发送请求] --> B[DispatcherServlet 接收请求]
    B --> C[HandlerMapping 找到 HandlerExecutionChain]
    C --> D[HandlerAdapter 适配并调用 Handler]
    D --> E[Handler 执行业务逻辑,返回 ModelAndView]
    E --> F[ViewResolver 解析逻辑视图为 View]
    F --> G[View 渲染 Model 数据]
    G --> H[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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

// 替代 web.xml 的 Java 配置类
public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

/**
* 1. 配置根 Spring 容器的配置类(扫描 Service、Dao 等非 Web 组件)
*/
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class}; // 根配置类
}

/**
* 2. 配置 DispatcherServlet 对应的 Web 容器的配置类(扫描 Controller、ViewResolver 等 Web 组件)
*/
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class}; // Web 配置类
}

/**
* 3. 配置 DispatcherServlet 拦截的 URL 模式
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"}; // 拦截所有请求(除了 JSP)
}
}

// ---------------------- 根配置类(RootConfig.java)----------------------
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
// 扫描 Service、Dao 等组件,排除 @Controller 和 @EnableWebMvc 注解的类(交给 Web 容器处理)
@ComponentScan(
basePackages = "com.example",
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = EnableWebMvc.class),
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = org.springframework.stereotype.Controller.class)
}
)
public class RootConfig {
// 配置数据源、事务管理器、MyBatis 等非 Web 组件
}

// ---------------------- Web 配置类(WebConfig.java)----------------------
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.ViewResolver;

@Configuration
@EnableWebMvc // 启用 Spring MVC 注解支持(如 @RequestMapping、@Controller)
@ComponentScan(basePackages = "com.example.controller") // 扫描 Controller 组件
public class WebConfig {

/**
* 配置 ViewResolver(JSP 视图解析器)
*/
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/"); // 视图前缀
resolver.setSuffix(".jsp"); // 视图后缀
resolver.setExposeContextBeansAsAttributes(true); // 允许在 JSP 中访问 Spring Bean
return resolver;
}

// 可额外配置拦截器、资源映射(如静态资源 /static/**)等
}

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {

// 配置静态资源映射
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 映射 /static/** 路径到 classpath:/static/ 目录(适合 Maven/Gradle 项目)
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");

// 映射 /images/** 路径到 /WEB-INF/images/ 目录(适合传统 Web 项目)
registry.addResourceHandler("/images/**")
.addResourceLocations("/WEB-INF/images/");
}

// 其他配置(如 ViewResolver)...
}

总结

Spring MVC 的核心是 “前端控制器 + 组件协作”,通过 DispatcherServlet 统一调度,配合 HandlerMapping、HandlerAdapter、ViewResolver 等组件,实现请求的高效处理和灵活扩展。Spring 3.2+ 引入的 Java 配置方式(AbstractAnnotationConfigDispatcherServletInitializer)进一步简化了配置流程,替代了传统的 web.xml,是现代 Spring MVC 项目的推荐配置方式

欢迎关注我的其它发布渠道