✅ 一、问题引导式答法(面试场景)
面试官问:
“SpringMVC 的请求是怎么一步步传到 Controller 的?DispatcherServlet 内部做了什么?”
🧠 二、一句话核心总结
DispatcherServlet是 SpringMVC 的核心控制器,负责请求的分发、参数解析、控制器调用、视图解析和响应输出,是整个请求流程的“调度中心”。
🔍 三、源码核心方法(doDispatch())流程图(文字版)
SpringMVC 请求主要由 DispatcherServlet 的 doDispatch() 方法驱动完成:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1. 获取处理器(Handler)
mappedHandler = getHandler(request);
// 2. 获取适配器(HandlerAdapter)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. 调用拦截器 preHandle()
// 4. 处理请求,调用 Controller 方法
mv = ha.handle(request, response, mappedHandler.getHandler());
// 5. 处理视图名称
processDispatchResult(request, response, mappedHandler, mv, dispatchException);
// 6. 调用拦截器 afterCompletion()
}
🔬 四、详细执行流程(逐步拆解)
| 步骤 | 说明 | 关键类/方法 |
|---|---|---|
| ① 请求进入 DispatcherServlet | 被 DispatcherServlet 捕获(Servlet 拦截路径为 /) | doService() → doDispatch() |
| ② 解析请求路径,寻找对应处理器 | 调用 HandlerMapping 获取 HandlerExecutionChain(包含 Controller 方法与拦截器链) | getHandler() |
| ③ 获取 HandlerAdapter | 根据处理器类型选择合适的适配器(支持注解、传统 Controller 等) | getHandlerAdapter() |
④ 调用拦截器链的 preHandle() 方法 | 执行用户自定义的拦截器逻辑(如登录校验) | HandlerInterceptor |
| ⑤ 执行 Controller 方法 | 实际调用用户编写的业务方法,返回 ModelAndView 或数据对象 | HandlerAdapter.handle() |
| ⑥ 视图解析 | 如果返回视图名,则用 ViewResolver 解析为页面路径;否则直接返回 JSON | processDispatchResult() |
| ⑦ 响应输出 | 页面渲染 or 返回 JSON 结果 | render() |
| ⑧ 拦截器链 afterCompletion 回调 | 异常处理、日志记录等 | afterCompletion() |
🔧 五、DispatcherServlet 的核心组件参与者
| 组件 | 作用 |
|---|---|
| HandlerMapping | 负责从请求路径匹配到对应的 Handler(Controller 方法) |
| HandlerAdapter | 执行 Handler 的适配器,统一调用方式 |
| ViewResolver | 将返回的视图名称解析为真正视图(JSP、HTML、Thymeleaf) |
| HttpMessageConverter | 将对象转换为 JSON(当返回的是 @ResponseBody) |
| HandlerInterceptor | 拦截器:执行前置、后置、最终操作 |
| ExceptionResolver | 异常统一处理入口,解析为友好响应或错误页 |
📋 六、标准答题模板(适合口述面试)
SpringMVC 的核心调度器是
DispatcherServlet,它接收请求后,会按照如下顺序执行:
首先通过
HandlerMapping匹配请求对应的 Handler(也就是 Controller 方法);然后通过
HandlerAdapter调用该方法;调用过程中还会执行拦截器的
preHandle();控制器方法执行完后,返回
ModelAndView或 JSON 数据;视图解析器
ViewResolver负责解析页面;如果是
@ResponseBody,则由HttpMessageConverter转换为 JSON;最后返回给前端,同时触发拦截器的
afterCompletion()做收尾处理。
📚 七、场景记忆辅助(举例)
| 场景 | DispatcherServlet 执行行为 |
|---|---|
请求 /user/list | 找到对应 UserController.list() 方法 |
返回页面名 userList | ViewResolver 解析为 /WEB-INF/views/userList.jsp |
| 返回 JSON 对象 | 使用 Jackson 的 MessageConverter 转换并输出 |
| 拦截未登录用户 | 拦截器 preHandle() 拦截请求并跳转登录页 |

1962

被折叠的 条评论
为什么被折叠?



