★ Spring MVC 请求处理全流程
结论先行:Spring MVC 以 DispatcherServlet(前端控制器) 为总入口。一次请求的完整调用:DispatcherServlet.doDispatch → HandlerMapping 根据 URL 找到 HandlerExecutionChain(处理器方法 + 拦截器链)→ HandlerAdapter 适配执行(参数解析器绑定入参、HttpMessageConverter 处理 @RequestBody)→ 执行 Controller 方法 → 返回结果由消息转换器写回或走 ViewResolver 渲染 → 过程异常交给 HandlerExceptionResolver → 最后拦截器 afterCompletion 收尾、响应返回。
一、关键步骤(按序)
- 请求到达 DispatcherServlet(继承 HttpServlet);
- HandlerMapping.getHandler:如 RequestMappingHandlerMapping 把 URL 映射到 HandlerMethod,并组装拦截器链;
- HandlerAdapter 选定:注解方法对应 RequestMappingHandlerAdapter;
- 执行拦截器 preHandle(任一返回 false 则中断);
- HandlerAdapter.handle:HandlerMethodArgumentResolver 解析 @PathVariable/@RequestParam/@RequestBody 等参数;
- 反射调用 Controller 方法,执行业务;
- 处理返回:@ResponseBody → HttpMessageConverter 序列化写回;返回视图名 → ViewResolver 解析、渲染 ModelAndView;
- 拦截器 postHandle(渲染前);
- 异常处理:Controller 抛出的异常经 HandlerExceptionResolver(@ExceptionHandler / @ControllerAdvice)统一处理;
- 拦截器 afterCompletion(无论成败都执行),响应返回。
@RestController
@RequestMapping("/orders")
public class OrderController {
@GetMapping("/{id}") // 步骤 2:被映射为 HandlerMethod
public Order detail(@PathVariable Long id) { // 步骤 5:参数解析器取路径变量
return orderService.get(id); // 步骤 7:@ResponseBody → JSON 写回
}
}
二、关键组件一句话
| 组件 | 职责 |
|---|---|
| DispatcherServlet | 前端控制器,调度一切 |
| HandlerMapping | URL → Handler + 拦截器链 |
| HandlerAdapter | 屏蔽 handler 类型差异,统一调用 |
| HandlerMethodArgumentResolver | 方法参数绑定 |
| HttpMessageConverter | @RequestBody/@ResponseBody 消息转换(JSON 等) |
| HandlerExceptionResolver | 统一异常出口 |
| ViewResolver | 视图名 → View |
常见追问 / 记忆点
- 追问 1:为什么需要 HandlerAdapter?答:让 DispatcherServlet 不感知 handler 具体类型(注解方法、Controller 接口、HttpRequestHandler 都能被适配调用),便于扩展。
- 追问 2:@ResponseBody 与 ModelAndView 路径区别?答:前者在 HandlerAdapter 内由消息转换器直接写响应(ModelAndView 为 null),后者走 ViewResolver 渲染。
- 追问 3:拦截器三个方法的执行时机?答:preHandle 在 Controller 前,postHandle 在渲染前,afterCompletion 在请求完成后。
- 记忆点:链路口诀——"调度找映射,映射出链,适配执行,异常处理器兜底,转换器/视图收尾"。