✅ 一、问题引导式答法(面试场景)
面试官问:
“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() 拦截请求并跳转登录页 |