Spring MVC 具体的工作原理?
- 标签:后端、Spring
🏛 业务架构师
Spring MVC 的请求处理管线:DispatcherServlet(统一前端控制器)→ HandlerMapping(找哪个 Controller 方法)→ HandlerAdapter(参数解析与调用)→ Controller → 返回 → 拦截器 postHandle → 结果处理(@ResponseBody 直接写 JSON / ViewResolver 渲染视图)→ 拦截器 afterCompletion。
业务视角,这条管线的价值是"标准化的扩展点体系"——公司的横切规范全部挂在管线上:
- HandlerInterceptor:登录态校验、权限检查、trace 注入、审计埋点——统一鉴权收口的物理位置,每个请求必经,没有绕过路径;
- HandlerMethodArgumentResolver:自定义参数解析(从 token 解出当前用户对象直接注入方法参数)——Controller 方法签名即业务契约,
Order create(@CurrentUser User u, @Valid CreateReq req)干净到不需要解释; - @ControllerAdvice + @ExceptionHandler:全局异常→业务错误码的统一翻译——错误码体系是前后端与多端联调的公共语言,散在各处的 try-catch 是腐化的起点;
- 消息转换器(HttpMessageConverter):统一 JSON 序列化策略(日期格式、空值处理、脱敏)。
两个工程要点:
- 过滤器(Filter)与拦截器(Interceptor)的分工:Filter 在 Servlet 层(编码、CORS、安全头等协议级),Interceptor 在 Spring 层(能拿到 Handler 信息,做业务级校验)——分层挂载,别混用;
- 异步与流式:DeferredResult/Callable 支撑长任务异步化、SseEmitter/ResponseBodyEmitter 支撑流式响应(AI 应用标配)——请求处理模型与业务交付形态要对齐。
一句话:理解 DispatcherServlet 管线不是为了背流程,是知道公司的横切治理该挂在哪一环——管线即治理地图。
🏗 系统架构师
Spring MVC 一次请求的完整链路(核心是 DispatcherServlet 的模板化分发):
- 请求到达:HTTP → 内嵌 Tomcat(Spring Boot)→ 经 Filter 链(编码、鉴权、链路追踪等横切处理)→ 到达 DispatcherServlet(前端控制器,统一入口);
- 处理器映射:DispatcherServlet 查 HandlerMapping 找到匹配的 Handler(@RequestMapping 注解方法)+ 拦截器链;
- 适配执行:HandlerAdapter 适配调用(参数解析:@RequestParam/@RequestBody 由 HttpMessageConverter 反序列化;数据校验、@InitBinder);
- 业务执行:Controller → Service(事务/AOP 代理在此生效)→ 返回 ModelAndView 或 @ResponseBody 对象;
- 结果处理:返回值经 HttpMessageConverter(Jackson)序列化;视图场景由 ViewResolver 解析视图再渲染;
- 异常处理:方法抛异常被 HandlerExceptionResolver(@ExceptionHandler/@ControllerAdvice)截获转统一响应;
- 响应返回:拦截器 afterCompletion → Filter 响应段 → 写回客户端。
设计模式贯穿:前端控制器(DispatcherServlet)、适配器(HandlerAdapter 支持多类 Controller)、策略(Resolver 族)、模板方法、责任链(Interceptor)。
工程视角:排障时沿这条链二分定位——没进 Controller 查 Filter/映射;进了但参数错查 Converter;响应慢查业务与慢 SQL;全局响应格式统一在 ControllerAdvice 收口。理解链路就是拥有排障地图。
💻 全栈开发专家
核心是 DispatcherServlet 的 doDispatch 一条链:
text
请求
→ DispatcherServlet.doDispatch()
→ HandlerMapping(RequestMappingHandlerMapping)
根据 URL+method 找到 HandlerExecutionChain(Controller 方法 + 拦截器链)
→ 拦截器 preHandle() ← 返回 false 直接返回
→ HandlerAdapter 适配调用 Controller 方法 ← 为什么需要 Adapter:
Controller 形态多样(@RequestMapping/传统接口),适配器统一调用协议
→ 参数解析(HandlerMethodArgumentResolver:@RequestBody/@PathVariable...)
→ 返回值处理(HandlerMethodReturnValueHandler)
→ 拦截器 postHandle()
→ 没有视图(@RestController)→ HttpMessageConverter(Jackson)写 JSON
→ 拦截器 afterCompletion()(无论成功失败都执行)必讲的两个扩展点(工程价值所在):
- 全局异常:
@RestControllerAdvice + @ExceptionHandler——把散落的 try-catch 收口,统一错误码结构:
java
@RestControllerAdvice
public class GlobalEx {
@ExceptionHandler(BizException.class)
public Result<Void> handle(BizException e) { return Result.fail(e.getCode(), e.getMsg()); }
}- 拦截器 vs 过滤器:Filter 是 Servlet 规范(最外层,拿不到 handler 信息);HandlerInterceptor 是 Spring 的(有 handler 上下文,登录态/日志用它)。
排障经验:404 看 HandlerMapping 是否注册(包扫描路径);参数 400 看 converter/validator;想看真实处理顺序直接断点 doDispatch,源码一遍过,比背时序图记得牢。