DispatcherServlet 请求处理流程与 MVC 组件协作
Spring MVC 建立在 Servlet 之上,它的心脏是一个名为 DispatcherServlet 的前端控制器(Front Controller)。学 MVC 先弄清 DispatcherServlet 的分派流程,后面的映射、拦截器、视图、异常处理才能串成一条线。
什么是前端控制器
所有进入应用的请求先到达 DispatcherServlet,由它把「找处理器、执行处理器、解析视图、渲染响应」等职责委托给各个 MVC 组件,而不是让每个 Controller 自己处理 Servlet 细节。
// 传统 web.xml 时代:所有 URL 都交给 DispatcherServlet(Servlet 3.0+ 可用 Java 方式注册,见第 40 章)
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
一次请求的完整流程(doDispatch)
DispatcherServlet 内部的核心方法是 doDispatch,大致按以下顺序协作:
- 设置请求上下文:根据 LocaleResolver、ThemeResolver 解析本地化与主题信息,并放入 LocaleContextHolder 等上下文。
- 解析 multipart:若容器中声明了 MultipartResolver 且当前请求是 multipart/form-data,则把请求包装为 MultipartHttpServletRequest。
- 找处理器:按注册顺序遍历所有 HandlerMapping,返回 HandlerExecutionChain(处理器 + 匹配的拦截器链)。
- 无处理器命中:走 noHandlerFound,默认返回 404(是否抛 NoHandlerFoundException 由配置决定,以官方文档为准)。
- 执行 preHandle:按顺序调用链上拦截器的 preHandle,任何一个返回 false 都会短路本次请求。
- 执行处理器:选择支持该处理器的 HandlerAdapter,由它解析方法参数并调用 @RequestMapping 方法。
- 异步分支:若处理器开启了异步(Callable/DeferredResult),Servlet 容器线程先返回,结果就绪后再次派发。
- 执行 postHandle:处理器已返回、视图渲染之前回调。
- 处理结果:把 ModelAndView(含逻辑视图名)交给 ViewResolver 解析成 View 并渲染;若抛异常则交给 HandlerExceptionResolver 链。
- 收尾:在 finally 中执行 afterCompletion、清理 multipart 临时文件、复位 RequestContextHolder。
请求 → DispatcherServlet → HandlerMapping → HandlerExecutionChain
→ HandlerAdapter → @Controller 方法 → ModelAndView
→ ViewResolver → View 渲染 → 响应
异常路径:Exception → HandlerExceptionResolver → 错误响应
DispatcherServlet 会探测的组件
DispatcherServlet 启动时会从自身的 WebApplicationContext 中探测一批「特殊 Bean」,缺省时使用内置默认实现:
| 组件 | 职责 | 无配置时的默认 |
|---|---|---|
| HandlerMapping | 请求 URL 映射到处理器 | RequestMappingHandlerMapping 等(有序) |
| HandlerAdapter | 调用处理器、解析参数/返回值 | RequestMappingHandlerAdapter 等 |
| HandlerExceptionResolver | 把异常转成响应 | ExceptionHandlerExceptionResolver 等 |
| ViewResolver | 逻辑视图名 → View | 按需配置(默认无) |
| LocaleResolver | 解析当前语言区域 | AcceptHeaderLocaleResolver |
| ThemeResolver | 解析主题 | FixedThemeResolver |
| MultipartResolver | 文件上传解析 | 默认无(需要时自行声明) |
| FlashMapManager | 重定向传参(Flash 属性) | SessionFlashMapManager |
多组件并存与优先级
同类型组件可以同时存在多个,例如同时支持注解控制器与静态资源处理器,它们靠 order 排序、由 DispatcherServlet 依次尝试。注解映射的优先级最高,静态资源、默认 Servlet 兜底排在最后,顺序细节以官方文档为准。
DispatcherServlet 把「分发」这件事做得很薄,真正的扩展点都在它委派的组件上:HandlerMapping 决定谁能处理、HandlerAdapter 决定怎么调用、拦截器在调用前后插入逻辑。记住 doDispatch 的这十条顺序,后面的章节都是往这条链上挂东西。