今天学完springMVC,大致总结一下它的工作流程
博客内容较长,请耐心看完
1. 用户向服务器发送请求,请求被前端控制器捕获,前端控制器对请求资源路径进行解析,判断请求对应的映射。
(1)当未找到请求映射的时候,并且未配置mvc:default-servlet-handler,会报如下错误。
由自己配置的前端控制器输出报错信息。
(2)当未找到请求映射的时候并且配置了mvc:default-servlet-handler,会报如下错误
由springMVC自己的默认处理器输出报错信息。
2. 找到请求映射的时候。映射处理器获取该handler配置的相关对象,最后以执行链对象返回。我们先进入到前端控制器的doDispatch方法。
(1)有三个成员变量,第一个handler 是请求对应的控制器方法,第二个是拦截器集合,第三个是拦截器下标
(2)点进getHandler方法
(3) 可以看到有一个handlerMappings成员变量
可以看到有五个handlerMapping,相当于这5个挨个进去比较
其中第一个RequestMappingHandlerMapping是标注@RequestMapping的方法信息以及其他handler方法。
(4)
可以看到lookupPath是我们请求的路径
我们点进这个方法
只根据请求路径找
这个方法其实就是把directPathMatcher里真正符合条件的方法给matches 集合,如果这个matches集合中有两个及以上,就会抛出异常,也就是说在控制器中不能有两个相同的方法。最后返回HandlerMethod.类型的对象。
总结就是:
- SpringBoot自动配置欢迎页的 WelcomePageHandlerMapping 。访问 /能访问到index.html;
- SpringBoot自动配置了默认 的 RequestMappingHandlerMapping
- 请求进来,挨个尝试所有的HandlerMapping看是否有请求信息。
- 如果有就找到这个请求对应的handler
- 如果没有就是下一个 HandlerMapping
3. 前端控制器根据获得的mappedHandler,找到合适的适配处理器(HandlerAdapter),即创建对象。
然后开始执行拦截器的preHandler方法。
4.正式开始处理控制器方法。
提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求。在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
a) HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
b) 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
c) 数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等
d) 数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
(1) Handler执行完成后,向DispatcherServlet 返回一个ModelAndview对象
(2)接着执行return返回视图名称
(3)接着映射处理器调用posthandler方法,并且调用是反向的(具体见下图)
跟进源码可知
5. 接着执行doDispatcher里的processDispatchResult方法
(1)进入此方法可知
(2)然后紧接着渲染视图
(3)渲染视图完毕后执行拦截器的afterCompletion方法(调用也是逆向的),如下图源码分析
6.将视图渲染结果返回给客户端
这就是mvc执行过程的全部流程了,如有错误,敬请斧正。