✿ 阅读源码思路:
先跳过非重点,深入每个方法,进入的时候可以把整个可以理一下方法的执行步骤理一下,也可以,理到某一步,继续深入,回来后,接着理清除下面的步骤。
✿ 阅读本文的准备工作,预习一下SpringMVC的执行流程
■ 解释一下,为什么标题是验证SpringMVC执行流程:
不知道小伙伴有没有做过物理实验的验证实验,道理是一样的,举个高中生都做过的物理实验吧----自由落体实验,这个实验是通过小钢球做抛物运动,验证重力加速度的g值是9.8。对于本文,咱的做法是通过调试来验证SpringMVC的执行流程是:
1、前端控制器接收到客户端的请求后,通过处理器映射器handlerMappings,根据路径urlPath去匹配选择处理器handler,最终返回一个处理器执行链对象HandlerExcutionChain。
2、前端控制器通过处理器适配器,调用处理器的方法,然后处理器执行后返回模型视图对象给处理器适配器,适配器再将模型视图对象返回给前端对象。
3、前端控制器通过视图解析器,将模型视图进行解析,然后将模型数据填充到View,并渲染到视图,然后返回响应。
🏓 SpirngMVC执行流程图(图片来源于叩丁狼)
![](https://img.haomeiwen.com/i27729824/f8e887c75b14a8e7.png)
一、执行流程前的次要源码
● 开始debug的时候,对HttpMethod感到好奇,点进去查看一下HttpMethod究竟是何物?
![](https://img.haomeiwen.com/i27729824/60453f299b949f9e.png)
- HttpMethod 是请求方法的枚举类,结合咱浏览器地址栏的参数是直接输入,
可以知道咱的HttpMethod的值是Get
![](https://img.haomeiwen.com/i27729824/8bf838da68d4e64e.png)
- 果然咱的HttpMethod的值是Get,所以下一步会执行super.service(request, response);
- ctr进入该方法看一下,究竟是何物,发现按ctr没有反应【
解决:重新打开该类的文件
】
![](https://img.haomeiwen.com/i27729824/3a8c809bc5152d56.png)
- 进入super.service(request, response);内部一探究竟:
- 发现这个service方法做的是请求分发操作,结合咱的请求方法是GET,所以下一步咱是到doGet方法去一探究竟~
![](https://img.haomeiwen.com/i27729824/e789cdbe028150da.png)
- 再进入processRequest方法~
![](https://img.haomeiwen.com/i27729824/d515f6ce2edab382.png)
- 进入发现重点是doService(request, response);那咱就进入该方法内部一探究竟吧~
![](https://img.haomeiwen.com/i27729824/c7455910e4c8ac86.png)
- 进入发现重点是doDispatch(request, response);那咱就进入该方法内部一探究竟吧~
![](https://img.haomeiwen.com/i27729824/9d1509e253337a69.png)
二、真正的springMVC执行流程的源码分析
<font color=orange>1、验证:前端控制器接收到客户端的请求后,通过处理器映射器handlerMappings,根据路径urlPath去匹配选择处理器handler,最终返回一个处理器执行链对象HandlerExcutionChain。</font>
● 获取处理器映射器返回处理器执行链对象,getHandler(processedRequest);方法
【<font color=blue>咱提前了解到的springMVC的执行过程:前端控制器接收请求,通过处理器映射器寻找处理器,返回一个处理器执行链对象
</font>】。
![](https://img.haomeiwen.com/i27729824/3eecf8c956780cf1.png)
● 发现了 this.handlerMappings 处理器映射器-观察它的值为:
[org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@40851021]【<font color=blue>咱提前了解到的springMVC的执行过程:前端控制器接收请求,通过处理器映射器
寻找处理器,返回一个处理器执行链对象</font>】。
![](https://img.haomeiwen.com/i27729824/63b074a5acbf5eab.png)
● 进入 mapping.getHandler(request); 方法内部:
![](https://img.haomeiwen.com/i27729824/e1df2f70a6a81c29.png)
● 进入返回处理器对象的getHandlerInternal方法内部:Object handler = lookupHandler(lookupPath, request);
【<font color=blue>咱提前了解到的springMVC的执行过程:前端控制器接收请求,通过处理器映射器依据路径进行匹配
来寻找处理器,返回一个处理器执行链对象</font>】。
![](https://img.haomeiwen.com/i27729824/58a4c8cb628f0d68.png)
● 进入lookupHandler方法内部:验证了通过处理器映射器依据路径进行匹配
来寻找处理器。还观察到urlPath的值,正是咱配置的处理器的路径
![](https://img.haomeiwen.com/i27729824/1b3a853e2de62ecf.png)
![](https://img.haomeiwen.com/i27729824/91e1ec0725c31c97.png)
---- 按照阅读源码观察步骤,到这一步,你已经理清楚了,可以调试回去,回去到:
![](https://img.haomeiwen.com/i27729824/3a6186eaad355c61.png)
......
<span color=Indigo> ✿ 至此,验证了SpringMVC的执行流程:前端控制器接收到客户端的请求后,通过处理器映射器handlerMappings,根据路径urlPath去匹配选择处理器handler,最终返回一个处理器执行链对象HandlerExcutionChain。</span>
<font color=orange>2、验证:前端控制器通过处理器适配器,调用处理器的方法,然后处理器执行后返回模型视图对象给处理器适配器,适配器再将模型视图对象返回给前端对象.</font>
● 获取处理器适配器对象HandlerAdapter
![](https://img.haomeiwen.com/i27729824/159ca3fae9d0923e.png)
● 进入getHandlerAdapter获取处理器适配器方法内部:
看到了this.handlerAdapters 处理器映射器
-观察它的值为:
[org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@60038152]
![](https://img.haomeiwen.com/i27729824/6ce215cb76cbab6e.png)
- 非重点:判断与“被修改”相关的
- 非重点:前置拦截器相关的
![](https://img.haomeiwen.com/i27729824/195599edbfabbcfa.png)
● 进入ha.handle方法内部观察:
![](https://img.haomeiwen.com/i27729824/c4d8ba843e516a33.png)
-
看到了(Controller) handler
-观察它的值为:
com.shan.hello.HelloController@591b274
![](https://img.haomeiwen.com/i27729824/14cd441a349392f0.png)
![](https://img.haomeiwen.com/i27729824/c8ff3be2133d2af5.png)
- `执行完((Controller) handler).handleRequest(request, response);即调用咱自己书写的处理器类的方法~``
- 返回,
继续观察,发现ModelAndView对象,观察它的值
:
ModelAndView [view="/WEB-INF/views/welcome.jsp"; model={msg=你好,easyMVC}]
![](https://img.haomeiwen.com/i27729824/f8328c329c22cda5.png)
- 这个深入进去,设置视图名称
![](https://img.haomeiwen.com/i27729824/6abfc93579f6831a.png)
- 非重点:后置拦截器
![](https://img.haomeiwen.com/i27729824/088b59f7f186d96e.png)
- 继续观察---观察到:处理分发的结果,深入进去观察:
![](https://img.haomeiwen.com/i27729824/bf608bb9d668f78f.png)
- 非重点:错误异常相关的
- 重点:渲染方法
![](https://img.haomeiwen.com/i27729824/c9a2bc4d88456265.png)
。。。。。。跟视图有关的重点。。。。。
<font color=Indigo>至此,验证了SpringMVC的执行流程:前端控制器通过处理器适配器HandlerAdapter,调用处理器HelloController的方法,然后处理器执行后返回模型视图对象ModelAndView给处理器适配器,适配器再将模型视图对象返回给前端控制器.</font>
<font color=orange>3、验证:前端控制器通过视图解析器,将模型视图进行解析,然后将模型数据填充到View,并渲染到视图,然后返回响应.</font>
- 非重点:国际化
- 非重点:视图名称
![](https://img.haomeiwen.com/i27729824/25d2e86386189d21.png)
● 重点:渲染视图
![](https://img.haomeiwen.com/i27729824/959a19ff546aa061.png)
![](https://img.haomeiwen.com/i27729824/b8b36609132a6bad.png)
- 观察到返回一个模型对象,根据方法调用的先后顺序,先调用了view.render(mv.getModelInternal(), request, response);的mv.getModelInternal()方法,需要重新深入一次
![](https://img.haomeiwen.com/i27729824/436417f4f9707558.png)
![](https://img.haomeiwen.com/i27729824/098c15c866773c23.png)
● 在渲染视图render方法内部,观察到mergedModel,观察它的值:
{msg=你好,easyMVC}
![](https://img.haomeiwen.com/i27729824/335c3e962df433cc.png)
- 非重点:预响应
● 重点:renderMergedOutputModel【<font color=blue>符合咱提前了解的SpringMVC的执行流程中渲染视图的数据</font>】
![](https://img.haomeiwen.com/i27729824/ca11f14e27d26973.png)
● 深入,发现是将共享数据设置到请求中去
![](https://img.haomeiwen.com/i27729824/0a483e3ff4fccb74.png)
● 接着往下,跳过非重点,来到请求转发
![](https://img.haomeiwen.com/i27729824/8dc409eeef552f40.png)
<font color=Indigo>至此,验证:前端控制器通过视图解析器,将模型视图进行解析,然后将模型数据填充到View,并渲染到视图,然后返回响应.</font>
写在后面的话
如果你觉得一乐的文章给您带来了一些收获,可以给个三连❤️ ,一乐会一如既往地更新有价值的博客。如果文章存在错误,也欢迎大家指出。还有,如果大家有什么好的学习技巧、学习感悟,也非常欢迎大家在评论区一起交流~
最后感谢大家的支持,谢谢~
网友评论