Spring MVC 将 DispatcherServlet 作为前端控制器,所有请求都先汇聚于此,再由它委派给其他组件协同处理。
Spring MVC 核心流程图
Spring MVC 核心工作流程(含源码关键调用点)
ViewResolver 视图解析
DispatcherServlet 核心调度
- 找处理器
- 返回 HandlerExecutionChain
- 找适配器
- 返回 HandlerAdapter
- 前置拦截
若 false 则中断
若 true 继续
执行业务方法
返回 ModelAndView 或直接响应 - 后置拦截
- 处理结果渲染
- 视图解析与渲染
- 最终响应
- 清理资源
HTTP Request
返回
doDispatch 入口
getHandler 遍历 HandlerMapping
getHandlerAdapter 获取匹配的 HandlerAdapter
applyPreHandle 执行拦截器 preHandle
HandlerAdapter.handle 执行 Controller 方法
applyPostHandle 执行拦截器 postHandle
processDispatchResult 处理结果和异常
render 视图渲染
triggerAfterCompletion 拦截器 afterCompletion
Controller / @RequestMapping 方法
resolveViewName 逻辑名 → View 对象
View.render 输出 HTML/JSON
流程详解(对照源码行号)
| 步骤 | 角色 / 关键代码位置 | 说明 |
|---|---|---|
| 1 | DispatcherServlet.doDispatch() line 920+ |
所有请求入口,开始调度。 |
| 2 | getHandler() -> 遍历 handlerMappings |
通过 URL 找到 HandlerExecutionChain(含 Handler + Interceptor 列表)。 |
| 3 | getHandlerAdapter() |
根据 Handler 类型找到能执行它的适配器(如 RequestMappingHandlerAdapter)。 |
| 4 | applyPreHandle() |
依次执行每个拦截器的 preHandle 方法,若返回 false 则请求短路。 |
| 5 | ha.handle() |
适配器调用实际 Controller 方法(通过反射),并封装返回值为 ModelAndView。 |
| 6 | applyPostHandle() |
执行拦截器的 postHandle 方法(在 Controller 之后、视图渲染之前)。 |
| 7 | processDispatchResult() |
统一处理 ModelAndView 或异常。 |
| 8 | render() -> ViewResolver.resolveViewName() |
根据逻辑视图名(如 "userList")解析出 View(如 InternalResourceView)。 |
| 9 | View.render() |
将模型数据与视图合并(如 JSP 渲染),输出到 HttpResponse。 |
| 10 | triggerAfterCompletion() |
执行拦截器的 afterCompletion 方法(无论是否异常,最终清理)。 |
图中使用了子图
DispatcherServlet和ViewResolver,并用不同颜色区分组件类型,流程箭头清晰标注了步骤序号,方便和源码对应。
精简版总结(一句话 + 一张表)
DispatcherServlet 接收请求 → HandlerMapping 定位 → HandlerAdapter 执行 → 拦截器干预 → 返回 ModelAndView → ViewResolver 渲染 → 输出响应
| 阶段 | 组件 | 源码方法 |
|---|---|---|
| 接收请求 | DispatcherServlet | doDispatch() |
| 定位处理器 | HandlerMapping | getHandler() |
| 执行处理器 | HandlerAdapter | ha.handle() |
| 视图解析 | ViewResolver | resolveViewName() |
| 视图渲染 | View | render() |
| 拦截器回调 | Interceptor | preHandle / postHandle / afterCompletion |
组件分析
核心组件(五大关键角色)
| 组件 | 职责 |
|---|---|
| DispatcherServlet | 中央调度器,接收请求并分发给其他组件 |
| HandlerMapping | 根据请求 URL 找到能处理它的 Handler(即 @RequestMapping 方法) |
| HandlerAdapter | 适配器:确保不同类型的 Handler 能以统一方式被调用执行 |
| ViewResolver | 根据逻辑视图名(如 "hello")解析出真正的 View 对象(如 hello.jsp) |
| View | 负责视图渲染,将 Model 数据填充到视图中 |
执行流程:源码逐步拆解
1. 请求入口:doDispatch(Request, Response)
DispatcherServlet 的 doDispatch 是处理所有请求的核心调度方法:
java
protected void doDispatch(HttpServletRequest request, HttpServletResponse response)
throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
ModelAndView mv = null;
// ... 上下文设置、异步处理等 ...
try {
// ✅ 1. 检查文件上传
processedRequest = checkMultipart(request);
// ✅ 2. 获取处理器执行链 (Handler + Interceptors)
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// ✅ 3. 获取支持该 Handler 的适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// ✅ 4. 执行所有拦截器的 preHandle 方法
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return; // 如果某个拦截器返回 false,流程中断
}
// ✅ 5. 核心!调用 Handler 执行业务逻辑,返回 ModelAndView
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// ✅ 6. 执行所有拦截器的 postHandle 方法
mappedHandler.applyPostHandle(processedRequest, response, mv);
// ✅ 7. 最终视图渲染与异常处理
processDispatchResult(processedRequest, response,
mappedHandler, mv, dispatchException);
} catch (Exception ex) {
// 统一异常处理
}
}
2. 处理器映射:getHandler(Request)
以下代码展示了如何为请求找到匹配的处理器:
java
protected HandlerExecutionChain getHandler(HttpServletRequest request) {
for (HandlerMapping hm : this.handlerMappings) {
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler; // 返回包含 Handler 和拦截器链的对象
}
}
return null;
}
3. 获取适配器:getHandlerAdapter(Handler)
以下代码展示了如何获取适配器:
java
protected HandlerAdapter getHandlerAdapter(Object handler) {
for (HandlerAdapter ha : this.handlerAdapters) {
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler...");
}
4. 业务执行:ha.handle(...) -> ModelAndView
适配器的 handle 方法内部会:
- 解析请求参数与
@PathVariable - 执行数据验证与类型转换
- 通过反射调用
Controller的具体方法 - 将返回值(数据、视图名)封装为
ModelAndView对象
5. 最终响应:processDispatchResult(...)
processDispatchResult 方法会调用 ViewResolver 将 ModelAndView 中的逻辑视图名解析为物理视图(如 JSP),并执行渲染。
java
private void processDispatchResult(HttpServletRequest request,
HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv,
Exception exception) throws Exception {
// 统一异常处理
// ...
if (mv != null) {
// 调用 ViewResolver 解析逻辑视图名
render(mv, request, response);
}
// 执行所有拦截器的 afterCompletion 方法
if (mappedHandler != null) {
mappedHandler.triggerAfterCompletion(request, response, null);
}
}
一个请求进来,从前到后的核心处理链就完整走通了:DispatcherServlet → HandlerMapping 定位方法 → HandlerAdapter 适配执行 → 反射调用业务代码,返回 ModelAndView → ViewResolver 与 View 渲染响应 → 中间穿插着 Interceptor 的拦截逻辑。
将 DispatcherServlet 类比为公司的前台总机,所有访客(请求)先到这里。总机根据来意查看地图(HandlerMapping )找到对应部门,找到后安排行政助理(HandlerAdapter )对接,业务办完后秘书将结果返回前台,再由总机指定专员(ViewResolver )制作最终的回执文件(View)交给访客。