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 等待下一次请求。

核心流程总结(简化版)

用户发送请求
DispatcherServlet 接收请求
HandlerMapping 找到 HandlerExecutionChain
HandlerAdapter 适配并调用 Handler
Handler 执行业务逻辑,返回 ModelAndView
ViewResolver 解析逻辑视图为 View
View 渲染 Model 数据
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 项目的推荐配置方式

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

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10