重要组件

1、HandlerMapping

代表请求地址到 handler 之间的映射。

2、HandlerExecutionChain

handler 的执行链对象,由 handler 对象和所有 handler 拦截器组成。SpringMVC 调用 HandlerMapping 接口中定义的 getHandler()方法获取该对象。

3、HandlerAdapter

执行请求参数注入、类型转换、数据验证等具体操作。

关键节点

1、获取 HandlerExecutionChain 对象

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:1101 行、916 行 Tips:如果当前请求没有经过映射,那么 mappedHandler 是否为 null 呢?

  • 如果配置了 mvc:default-servlet-handler 则不为 null
  • 如果没有配置 mvc:default-servlet-handler 则为 null

2、获取 HandlerAdapter 对象

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:923 行

3、调用拦截器的 preHandle()方法

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:939 行

4、为模型对象注入请求参数

所在 API:org.springframework.web.bind.annotation.support.HandlerMethodInvoker 源码位置:170 行、373 行

5、调用目标 handler 方法

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:945 行

6、调用拦截器的 postHandle()方法

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:954 行

7、处理视图转发相关

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:959 行

8、处理异常

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:998 行

9、渲染视图

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:1012 行

① 解析视图名称,将逻辑视图转换为物理视图

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:1204 行、1266 行

② 渲染视图

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:1225 行

③ 将模型数据暴露到请求域

所在 API:org.springframework.web.servlet.view.AbstractView 源码位置:266 行

④ 将模型数据保存到请求域

所在 API:org.springframework.web.servlet.view.AbstractView 源码位置:374 行

⑤ 转发

所在 API:org.springframework.web.servlet.view.InternalResourceView 源码位置:209 行

10、调用拦截器的 afterCompletion 方法

所在 API:org.springframework.web.servlet.DispatcherServlet 源码位置:1030 行

annotation 相关

我们在前面的操作中发现,使用了mvc:default-servlet-handlermvc:view-controller后必须使用mvc:annotation-driven

关键原因是他们加载使用的HandlerMapping不同。

1、三个都没有使用时有效的 HandlerMapping

org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

其中DefaultAnnotationHandlerMapping负责把所有 handler 类中的 handler 方法收集起来。

2、增加了 mvc:default-servlet-handler 或 mvc:view-controller 后有效的 HandlerMapping

org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping

很明显,DefaultAnnotationHandlerMapping没了,而SimpleUrlHandlerMapping只能映射静态资源。

所以我们通过@RequestMapping 映射的 handler 方法无效了。

3、增加了 mvc:annotation-driven 后

org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping

加入了mvc:annotation-driven后最关键的是增加了RequestMappingHandlerMapping,从而可以映射我们的 handler 方法。