Spring MVC 是 Spring 框架的核心模块之一,其请求处理机制以 DispatcherServlet 为中心,实现高效的请求分发、处理和响应渲染。本指南基于 Spring Framework 6.x+ 版本(2026 年最新),通过源码级深度剖析全链路:从 DispatcherServlet 的初始化,到请求接收、Handler 映射、执行、异常处理,直至 View 解析和返回值渲染。所有源码片段来源于官方仓库(org.springframework.web.servlet.DispatcherServlet),结合实战配置示例,帮助你彻底掌握。
为了直观,我们先看 Spring MVC 请求处理流程图:
1. DispatcherServlet 概述与初始化
DispatcherServlet 是 Spring MVC 的前端控制器(Front Controller),继承自 HttpServlet,负责接收所有 HTTP 请求,并根据配置委托给合适的组件处理。它不直接处理业务逻辑,而是协调 HandlerMapping、HandlerAdapter 等组件,形成 MVC 模式。
初始化过程(init 方法)
- 加载上下文:DispatcherServlet 在 Servlet 初始化时加载 WebApplicationContext(默认从 XML 或注解配置)。
- 检测组件:自动检测并注册默认的 HandlerMapping、HandlerAdapter、ViewResolver 等(如果未自定义)。
- 关键源码(DispatcherServlet.initStrategies):
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
- 配置示例(Java 配置,使用 @EnableWebMvc):
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.example")
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
- web.xml 配置(传统方式):
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2. 请求处理全链路:doService 与 doDispatch
请求到达 DispatcherServlet 后,首先调用 doService(HttpServlet 的入口),然后进入核心方法 doDispatch。这里是全链路的灵魂,处理从请求映射到响应渲染的所有步骤。
doService 源码剖析
- 准备请求:设置请求属性,如 WebApplicationContext。
- 委托 doDispatch:核心分发逻辑。
@Override
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
// ... 日志和属性设置
try {
doDispatch(request, response);
} finally {
// 清理
}
}
doDispatch 源码深度解析(全链路步骤)
doDispatch 是 DispatcherServlet 的心脏,逐行剖析:
- 检查 Multipart:如果有文件上传,使用 MultipartResolver 包装请求。
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
// ... 检查 Multipart
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
- 获取 Handler:通过 HandlerMapping(如 RequestMappingHandlerMapping)查找匹配的 Handler(@Controller 方法)。
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
- 获取 Adapter:使用 HandlerAdapter(如 RequestMappingHandlerAdapter)执行 Handler。
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
- 执行拦截器 preHandle:HandlerInterceptor 的前置处理。
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
- 执行 Handler:调用实际的 Controller 方法,返回 ModelAndView。
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
- 执行拦截器 postHandle:后置处理。
mappedHandler.applyPostHandle(processedRequest, response, mv);
- 处理结果:渲染 View 或处理异常。
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
- 完整 doDispatch 源码 skeleton:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 步骤1: Multipart 检查
// 步骤2: HandlerMapping 获取 HandlerExecutionChain
// 步骤3: HandlerAdapter 获取
// 步骤4: preHandle
// 步骤5: handle 执行
// 步骤6: postHandle
// 步骤7: processDispatchResult (View 渲染或异常)
// finally: afterCompletion
}
3. 核心组件深度:HandlerMapping 与 HandlerAdapter
- HandlerMapping:映射请求到 Handler。默认:RequestMappingHandlerMapping(基于 @RequestMapping)。
- 源码:AbstractHandlerMapping.getHandler() 通过 URL 匹配 Annotation。
- HandlerAdapter:执行 Handler。默认:RequestMappingHandlerAdapter。
- 支持 @Controller、参数解析(@PathVariable 等)、返回值处理(@ResponseBody)。
- 源码:handleInternal() 调用 invokeHandlerMethod() 执行方法。
示例 Controller:
@Controller
@RequestMapping("/api")
public class ExampleController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("message", "Hello, Spring MVC!");
return "helloView"; // 逻辑视图名
}
}
4. 异常处理:HandlerExceptionResolver
- 默认:DefaultHandlerExceptionResolver 处理标准异常;@ExceptionHandler 支持自定义。
- 源码:processHandlerException() 遍历 Resolvers。
示例:
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex) {
ModelAndView mav = new ModelAndView("error");
mav.addObject("error", ex.getMessage());
return mav;
}
5. 返回值解析与 ViewResolver
- ModelAndView 处理:如果返回 ModelAndView 或 String(视图名),ViewResolver 解析为实际 View(如 JSP)。
- @ResponseBody:HttpMessageConverter 直接序列化 JSON/XML(Jackson/Gson)。
- ViewResolver:InternalResourceViewResolver 拼接 prefix + viewName + suffix。
源码:render() in DispatcherServlet:
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
// Locale/Theme 应用
View view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
view.render(mv.getModelInternal(), request, response);
}
总结与最佳实践
通过以上源码剖析,你看到 DispatcherServlet 如何协调组件实现 MVC 全链路:高效、模块化、可扩展。实践建议:在 IntelliJ 中调试 DispatcherServlet.doDispatch,逐步跟踪。进一步探索:Spring Boot 的自动配置简化了这些(@SpringBootApplication 隐含 @EnableWebMvc)。
如果需要特定版本源码 diff 或扩展如 REST 支持,随时提供细节!🚀