前面 4 篇我们讲解了 Spring IOC、AOP、SpringBoot 自动配置、Spring 事务。本篇作为 Spring 全家桶系列收尾,讲解 SpringMVC,也就是 Spring 体系的 Web 层框架。 SpringBoot 的 Web 能力底层就是 SpringMVC,日常写@RestController、@RequestMapping接口,都是 SpringMVC 的能力。很多开发只会写 Controller 接口,但是不清楚一次 HTTP 请求从浏览器到后端,再返回响应,完整经历了哪些组件;不理解参数解析、JSON 序列化、拦截器、全局异常处理器底层原理。本文从 MVC 设计思想、DispatcherServlet、九大组件、完整请求流程、参数绑定、HttpMessageConverter、拦截器、开发踩坑完整拆解。
前言
MVC 是经典分层架构:Model(模型数据)、View(视图)、Controller(控制器)。 传统 Servlet 开发:每个请求对应一个 Servlet,大量重复代码,手动解析 request 参数、封装 response,耦合严重,维护困难。
SpringMVC 基于前端控制器(Front Controller)模式,所有请求统一交给DispatcherServlet接收,由 DispatcherServlet 调度各个可插拔组件完成请求处理。
SpringMVC 构建在 Servlet 规范之上,同时依托 Spring IOC 容器,Controller、拦截器、异常处理器全部作为 Bean 托管。 SpringBoot 内置 SpringMVC,自动装配 DispatcherServlet,不需要 web.xml 配置。
一、核心:DispatcherServlet(前端控制器)
DispatcherServlet是整个 SpringMVC 的入口,本质是一个 Servlet。 职责:
- 拦截全部 HTTP 请求;
- 协调九大组件,调度请求处理链路;
- 捕获处理过程中的异常,交给异常解析器;
- 最终渲染视图 / 写出响应返回客户端。
核心设计思想:单一职责 + 可插拔组件。DispatcherServlet 只做调度,具体工作交给 HandlerMapping、HandlerAdapter 等组件完成,组件可以自定义替换、扩展。
二、SpringMVC 九大核心组件
全部由 Spring IOC 管理,DispatcherServlet 启动时自动加载这些 Bean。
- HandlerMapping 处理器映射器 根据请求 URL、请求方式(GET/POST)、请求头,查找匹配的 Handler(标注 @RequestMapping 的 Controller 方法,叫 HandlerMethod),同时把匹配的拦截器一起封装返回。
常用实现:
RequestMappingHandlerMapping,处理@RequestMapping注解。
- HandlerAdapter 处理器适配器 DispatcherServlet 不直接调用 Handler,通过适配器模式执行 Handler。 不同类型 Handler 有不同执行方式,适配器屏蔽差异。最常用
RequestMappingHandlerAdapter,负责执行注解 Controller 方法,内部包含参数解析器、返回值处理器。 - HandlerExceptionResolver 异常解析器 Controller、拦截器执行抛出异常时,由异常解析器捕获,处理异常,封装返回结果。我们开发的全局异常处理器就是实现这个接口。
- ViewResolver 视图解析器 把逻辑视图名称(如
"user/list")解析为 View 视图对象。前后端分离项目用@RestController直接返回 JSON,不会走视图渲染。
如 ThymeleafViewResolver、InternalResourceViewResolver(JSP)。
- View 视图 负责渲染模型数据,生成 HTML 页面。前后端分离项目基本不用。
- MultipartResolver 文件上传解析器 解析 multipart/form-data 类型请求,封装文件上传对象。
- LocaleResolver 国际化解析器 解析请求对应的区域语言(zh-CN、en-US),用于国际化页面。
- ThemeResolver 主题解析器 页面主题样式解析,现在很少使用。
- FlashMapManager 闪存管理器 重定向时传递临时参数,避免参数放在 URL 上。
重点记忆:日常开发最核心 4 个组件:DispatcherServlet、HandlerMapping、HandlerAdapter、HandlerExceptionResolver。
三、一次 HTTP 请求完整执行流程(核心)
浏览器发起 HTTP 请求 → Tomcat 接收请求 → 交给 DispatcherServlet
阶段 1:HandlerMapping 查找处理器
DispatcherServlet 遍历所有 HandlerMapping,根据 URL、请求方法 匹配,找到对应的 HandlerMethod,同时组装匹配的拦截器链 HandlerExecutionChain。
找不到匹配 Handler,直接返回 404。
阶段 2:执行拦截器 preHandle ()
按顺序执行拦截器的 preHandle()
任意一个
preHandle返回false:直接终止请求,返回响应,不会执行 Controller。
阶段 3:寻找 HandlerAdapter
DispatcherServlet 查找能够支持当前 HandlerMethod 的适配器,常用:RequestMappingHandlerAdapter。
阶段 4:参数绑定与解析(参数解析器 ArgumentResolver)
HandlerAdapter 调用参数解析器,从 HttpServletRequest 解析各类参数:
- URL 路径变量:
@PathVariable - URL 查询参数 / 表单参数:
@RequestParam - 请求体 JSON:
@RequestBody(依赖 HttpMessageConverter) - Header、Cookie、实体对象
解析完成后,自动做类型转换、JSR303 参数校验,组装成 Controller 方法入参。
阶段 5:执行 Controller 业务方法
调用 Controller 方法,执行业务代码,拿到方法返回值。
阶段 6:返回值处理器处理返回结果
HandlerAdapter 使用返回值处理器对返回值做处理:
- 标记
@ResponseBody:通过 HttpMessageConverter 将对象序列化为 JSON,写入 response body; - 普通字符串返回:视为逻辑视图名称,进入视图渲染流程。
阶段 7:执行拦截器 postHandle ()
Controller 方法正常执行完毕后、视图渲染之前执行 postHandle。
如果 Controller 抛出异常,
postHandle不会执行。
阶段 8:视图渲染(前后端分离项目直接跳过)
如果返回 ModelAndView / 视图名称:ViewResolver 解析视图,View 渲染页面。
阶段 9:执行拦截器 afterCompletion ()
视图渲染完成后执行。
无论 Controller 正常执行还是抛出异常,都会执行,适合写资源释放逻辑。
阶段 10:异常兜底处理
整个链路任意环节抛出异常,都会交给 HandlerExceptionResolver 统一捕获,封装错误响应。
一句话精简流程: 请求→DispatcherServlet→HandlerMapping 找 Handler→拦截器 preHandle→HandlerAdapter→参数解析→调用 Controller→处理返回值→postHandle→视图渲染→afterCompletion→返回响应。
四、关键模块详解
4.1 HttpMessageConverter 消息转换器
作用:负责请求体序列化、响应体反序列化。
- 读请求:把 Request Body 的 JSON 字符串转为 Java 对象(
@RequestBody); - 写响应:把 Java 对象序列化为 JSON 字符串写入 Response(
@ResponseBody)。
SpringBoot 默认配置MappingJackson2HttpMessageConverter,底层 Jackson。
坑点:
@RequestBody只能读取 POST 请求 body,不能读取 url 参数;Content-Type 必须是 application/json。
4.2 拦截器 HandlerInterceptor
三个方法:
preHandle:Controller 执行之前;返回 true 放行,false 拦截。适合登录校验、token 校验。postHandle:Controller 执行成功,视图渲染之前;可以修改 Model 数据。异常不会执行。afterCompletion:请求全部完成,视图渲染完毕;无论是否异常都会执行,资源清理。
拦截器和过滤器 Filter 区别
- Filter:Servlet 规范,属于 Tomcat,在 DispatcherServlet之前执行;只能拿到 request、response;
- HandlerInterceptor:SpringMVC 组件,在 DispatcherServlet 内部,Controller 前后执行;可以拿到 HandlerMethod 对象,Spring Bean。
4.3 @Controller 和 @RestController
@Target(ElementType.TYPE)
@RestController = @Controller + @ResponseBody
@Controller:返回视图页面;@RestController:类上自带@ResponseBody,所有方法返回值直接写入响应体,不走视图解析。
五、常用注解原理
@RequestMapping:派生注解@GetMapping/@PostMapping,在容器启动阶段,被RequestMappingHandlerMapping扫描,把 URL 和 HandlerMethod 存入映射注册表。@RequestParam:解析 url 查询参数、表单参数。@PathVariable:解析 URL 路径占位符。@RequestBody:使用消息转换器读取请求体 JSON。@RequestHeader:读取请求头。
六、开发实战踩坑清单
- GET 请求不能使用 @RequestBody GET 没有请求体,
@RequestBody读取 body 会报错;GET 参数用@RequestParam、@PathVariable。 - 拦截器 preHandle 返回 false,afterCompletion 仍然会执行;但是 postHandle 不会执行。
- 全局异常处理器只能捕获 Controller 内抛出的异常;Filter 中抛出的异常,SpringMVC 异常解析器捕获不到。
- 参数绑定类型转换失败、JSR303 校验失败,会抛出 MethodArgumentNotValidException,交给全局异常处理器。
@ResponseBody依赖 HttpMessageConverter,如果没有 Jackson 依赖,JSON 序列化失败。- 静态资源(html、图片)默认不走 Controller,DispatcherServlet 放行静态资源。
- 跨域问题:浏览器同源策略。可以使用
@CrossOrigin注解,或者 WebMvcConfigurer 统一配置跨域。
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET","POST");
}
}
注意:allowCredentials=true 时,allowedOrigins 不能写
*,会冲突。
WebMvcConfigurer 不要加@EnableWebMvc;加上之后 SpringBoot 自动配置失效,全部 MVC 配置需要自己手动配置。
七、SpringMVC 和 SpringBoot 的关系
SpringBoot Web Starter 自动装配 SpringMVC: 自动创建 DispatcherServlet、自动装配 HandlerMapping、HandlerAdapter、消息转换器、视图解析器等组件。
如果不使用 SpringBoot,SSM 项目需要在 xml 手动注册 DispatcherServlet 和 MVC 组件。
八、问答汇总
Q1:SpringMVC 的执行流程?
A:浏览器请求到达 DispatcherServlet,HandlerMapping 匹配 url 找到 Handler 和拦截器链;执行拦截器 preHandle;HandlerAdapter 解析请求参数,调用 Controller 方法;返回值处理器处理结果;执行 postHandle;视图渲染;执行 afterCompletion;异常交给异常解析器处理。
Q2:Filter 和 Interceptor 的区别?
A:Filter 属于 Servlet 规范,Tomcat 执行,在 DispatcherServlet 之前;Interceptor 是 SpringMVC 组件,在 DispatcherServlet 内部,Controller 前后执行。Filter 只能操作 request、response;Interceptor 可以拿到 HandlerMethod,依赖 Spring 容器。
Q3:HttpMessageConverter 作用?
A:消息转换器,负责请求体 JSON 转 Java 对象(@RequestBody),Java 对象序列化为 JSON 写入响应(@ResponseBody)。SpringBoot 默认使用 Jackson。
Q4:九大组件简单说几个?
A:DispatcherServlet 调度,HandlerMapping 映射处理器,HandlerAdapter 执行处理器,HandlerExceptionResolver 异常处理,ViewResolver 视图解析器,MultipartResolver 文件上传解析器。
Q5:@RestController 是什么?
A:@Controller + @ResponseBody,类上所有方法返回值直接写入 response body,不进行视图解析,前后端分离开发常用。
Q6:preHandle、postHandle、afterCompletion 执行顺序和异常场景?
A:正常流程:preHandle → Controller → postHandle → afterCompletion。 Controller 抛出异常:preHandle 执行,postHandle 不执行,afterCompletion 依然执行。preHandle 返回 false 直接终止,afterCompletion 执行。
Q7:@EnableWebMvc 作用?
A:开启 SpringMVC 完全手动配置,会覆盖 SpringBoot 的 Web 自动配置,消息转换器、静态资源等自动配置失效,一般业务项目不要加。
结语
SpringMVC 是 Spring 全家桶 Web 层的核心,和前面 IOC、AOP 一脉相承。DispatcherServlet 本身是 IOC 容器中的 Bean,Handler、拦截器、异常处理器全部托管在 IOC;AOP 可以作用在 Controller、Service 方法上。 理解 SpringMVC,你就能打通从 HTTP 请求 → Web 层 → Service 层 → 数据库的完整链路。 至此,Spring 全家桶系列 5 篇博客全部完成:
- Spring IOC 容器原理
- Spring AOP 原理
- SpringBoot 自动配置 + 自定义 Starter
- Spring 事务(声明式 & 编程式)
- SpringMVC 原理
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/m0_63990694/article/details/167704848



