DispatcherServlet 是总调度员,负责拦截请求并协调 HandlerMapping、HandlerAdapter、ViewResolver 等组件;其启动依赖 Servlet 容器注册,初始化时加载默认组件,请求匹配、参数解析、视图渲染等均按固定顺序执行。

Spring MVC 的执行流程不是靠背出来的,而是得看清楚每个组件在什么时机、以什么方式参与进来。核心结论就一条:DispatcherServlet 是总调度员,它不干活,但所有活都得它点头才能开始。
DispatcherServlet 怎么启动并接管请求?
它本质是个 Servlet,靠 web.xml 或 Spring Boot 的自动配置注册进 Servlet 容器(如 Tomcat)。一旦注册成功,所有匹配 / 或 /*.do 等 pattern 的 HTTP 请求,都会被它拦截。
关键点:
-
DispatcherServlet初始化时会主动从ApplicationContext中查找并加载默认组件(如HandlerMapping、HandlerAdapter、ViewResolver),也可以通过配置显式指定 - 它本身不解析 URL 路径,而是把请求丢给注册的
HandlerMapping实例去匹配 - 如果没配任何
HandlerMapping,它会用默认的RequestMappingHandlerMapping—— 这就是为什么加了@Controller+@RequestMapping就能响应请求
HandlerMapping 找不到 handler 会怎样?
常见现象是返回 404,但原因可能不止“路径写错了”。真实排查顺序应该是:
立即学习“Java免费学习笔记(深入)”;
- 确认请求 URL 是否匹配
DispatcherServlet的url-pattern(比如 Spring Boot 默认是/**,而老项目常配成/app/*,这时访问/api/xxx就根本进不来) - 确认目标类是否被 Spring 扫描到:
@Controller类必须在@ComponentScan范围内,且不能是普通 new 出来的对象 - 确认方法上的注解是否有效:
@GetMapping("/user")等价于@RequestMapping(value = "/user", method = RequestMethod.GET);若写了method = POST却用 GET 访问,也会 404(实际是 405,但前端常误判为 404) - 注意路径拼接:若类上写了
@RequestMapping("/api"),方法上写了@GetMapping("v1/user"),完整路径是/api/v1/user,不是/api//v1/user(多斜杠一般会被容器 normalize,但容易干扰判断)
HandlerAdapter 执行 Controller 方法时传参怎么来的?
不是反射一调就完事。参数值来源五花八门,HandlerAdapter(实际是 RequestMappingHandlerAdapter)会根据参数类型和注解,委托给不同的 HandlerMethodArgumentResolver:
这本书给出了一份关于python这门优美语言的精要的参考。作者通过一个完整而清晰的入门指引将你带入python的乐园,随后在语法、类型和对象、运算符与表达式、控制流函数与函数编程、类及面向对象编程、模块和包、输入输出、执行环境等多方面给出了详尽的讲解。如果你想加入 python的世界,David M beazley的这本书可不要错过哦。 (封面是最新英文版的,中文版貌似只译到第二版)
-
@RequestParam→ 从 query string 或 form data 取值(注意:默认required = true,没传就抛MissingServletRequestParameterException) -
@PathVariable→ 从 URI 模板中提取(如/user/{id}中的id) -
@RequestBody→ 用HttpMessageConverter(如Jackson2ObjectMapper)反序列化请求体,要求 Content-Type 是application/json等可识别类型 - 无注解的 POJO 参数 → 自动做数据绑定(property match),支持嵌套对象、集合,但字段名必须严格匹配(大小写敏感)
最容易踩的坑是:前端传了 {"userName":"abc"},后端用 User user 接收,但 User 里字段叫 username(小写),结果绑定失败为 null —— 因为默认不忽略大小写,也不自动下划线转驼峰。
ModelAndView 和 ViewResolver 怎么配合渲染页面?
Controller 方法返回 String(如 "user/list")或 ModelAndView,只是逻辑视图名,不是真实路径。真正定位 HTML 或 JSP 文件的是 ViewResolver:
-
InternalResourceViewResolver最常用,会拼前缀后缀:prefix="/WEB-INF/views/"+"user/list"+suffix=".jsp"→/WEB-INF/views/user/list.jsp -
ThymeleafViewResolver不拼后缀,但要求模板文件名必须严格等于视图名(user/list.html) - 返回
ResponseEntity>或加了@ResponseBody,则跳过ViewResolver,直接走HttpMessageConverter写响应体
一个典型故障:明明有 /templates/user/list.html,却报 TemplateInputException: Error resolving template "user/list" —— 很可能是 spring.thymeleaf.prefix 配成了 classpath:/templates/,但实际路径是 src/main/resources/templates/(Maven 标准结构没问题),问题出在 IDE 没刷新 resources 或打包时漏了该目录。
整个流程里最易被忽略的,是 HandlerInterceptor 的执行时机:它夹在 HandlerMapping 找到 handler 之后、HandlerAdapter 执行之前,且 preHandle 返回 false 会直接中断流程,连 controller 都不会进 —— 日志里既看不到 controller 入口,也看不到异常堆栈,只看到请求“静默消失”。









