✿ 閱讀原始碼思路:
先跳過非重點,深入每個方法,進入的時候可以把整個可以理一下方法的執行步驟理一下,也可以,理到某一步,繼續深入,回來後,接著理清除下面的步驟。
✿ 閱讀本文的準備工作,預習一下SpringMVC的執行流程
■ 解釋一下,為什麼標題是驗證SpringMVC執行流程:
不知道小夥伴有沒有做過物理實驗的驗證實驗,道理是一樣的,舉個高中生都做過的物理實驗吧----自由落體實驗,這個實驗是通過小鋼球做拋物運動,驗證重力加速度的g值是9.8。對於本文,我們的做法是通過除錯來驗證SpringMVC的執行流程是:
1、前端控制器接收到客戶端的請求後,通過處理器對映器handlerMappings,根據路徑urlPath去匹配選擇處理器handler,最終返回一個處理器執行鏈物件HandlerExcutionChain。
2、前端控制器通過處理器介面卡,呼叫處理器的方法,然後處理器執行後返回模型檢視物件給處理器介面卡,介面卡再將模型檢視物件返回給前端物件。
3、前端控制器通過檢視解析器,將模型檢視進行解析,然後將模型資料填充到View,並渲染到檢視,然後返回響應。
? SpirngMVC執行流程圖(圖片來源於叩丁狼)
一、執行流程前的次要原始碼
● 開始debug的時候,對HttpMethod感到好奇,點進去檢視一下HttpMethod究竟是何物?
-
HttpMethod 是請求方法的列舉類,結合我們瀏覽器位址列的引數是直接輸入,
可以知道我們的HttpMethod的值是Get
-
果然我們的HttpMethod的值是Get,所以下一步會執行super.service(request, response);
-
ctr進入該方法看一下,究竟是何物,發現按ctr沒有反應【
解決:重新開啟該類的檔案
】
-
進入super.service(request, response);內部一探究竟:
-
發現這個service方法做的是請求分發操作,結合我們的請求方法是GET,所以下一步我們是到doGet方法去一探究竟~
-
再進入processRequest方法~
-
進入發現重點是doService(request, response);那我們就進入該方法內部一探究竟吧~
-
進入發現重點是doDispatch(request, response);那我們就進入該方法內部一探究竟吧~
二、真正的springMVC執行流程的原始碼分析
1、驗證:前端控制器接收到客戶端的請求後,通過處理器對映器handlerMappings,根據路徑urlPath去匹配選擇處理器handler,最終返回一個處理器執行鏈物件HandlerExcutionChain。
● 獲取處理器對映器返回處理器執行鏈物件,getHandler(processedRequest);方法
【我們提前瞭解到的springMVC的執行過程:前端控制器接收請求,通過處理器對映器尋找處理器,返回一個處理器執行鏈物件
】。
● 發現了 this.handlerMappings 處理器對映器-觀察它的值為:
[org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping@40851021]【我們提前瞭解到的springMVC的執行過程:前端控制器接收請求,通過處理器對映器
尋找處理器,返回一個處理器執行鏈物件】。
● 進入 mapping.getHandler(request); 方法內部:
● 進入返回處理器物件的getHandlerInternal方法內部:Object handler = lookupHandler(lookupPath, request);
【我們提前瞭解到的springMVC的執行過程:前端控制器接收請求,通過處理器對映器依據路徑進行匹配
來尋找處理器,返回一個處理器執行鏈物件】。
● 進入lookupHandler方法內部:驗證了通過處理器對映器依據路徑進行匹配
來尋找處理器。還觀察到urlPath的值,正是我們配置的處理器的路徑
---- 按照閱讀原始碼觀察步驟,到這一步,你已經理清楚了,可以除錯回去,回去到:
......
✿ 至此,驗證了SpringMVC的執行流程:前端控制器接收到客戶端的請求後,通過處理器對映器handlerMappings,根據路徑urlPath去匹配選擇處理器handler,最終返回一個處理器執行鏈物件HandlerExcutionChain。
2、驗證:前端控制器通過處理器介面卡,呼叫處理器的方法,然後處理器執行後返回模型檢視物件給處理器介面卡,介面卡再將模型檢視物件返回給前端物件.
● 獲取處理器介面卡物件HandlerAdapter
● 進入getHandlerAdapter獲取處理器介面卡方法內部:
看到了this.handlerAdapters 處理器對映器
-觀察它的值為:
[org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@60038152]
- 非重點:判斷與“被修改”相關的
- 非重點:前置攔截器相關的
● 進入ha.handle方法內部觀察:
看到了(Controller) handler
-觀察它的值為:
com.shan.hello.HelloController@591b274
-
`執行完((Controller) handler).handleRequest(request, response);即呼叫我們自己書寫的處理器類的方法~``
-
返回,
繼續觀察,發現ModelAndView物件,觀察它的值
:
ModelAndView [view="/WEB-INF/views/welcome.jsp"; model={msg=你好,easyMVC}]
-
這個深入進去,設定檢視名稱
-
非重點:後置攔截器
-
繼續觀察---觀察到:處理分發的結果,深入進去觀察:
-
非重點:錯誤異常相關的
-
重點:渲染方法
。。。。。。跟檢視有關的重點。。。。。
至此,驗證了SpringMVC的執行流程:前端控制器通過處理器介面卡HandlerAdapter,呼叫處理器HelloController的方法,然後處理器執行後返回模型檢視物件ModelAndView給處理器介面卡,介面卡再將模型檢視物件返回給前端控制器.
3、驗證:前端控制器通過檢視解析器,將模型檢視進行解析,然後將模型資料填充到View,並渲染到檢視,然後返回響應.
- 非重點:國際化
- 非重點:檢視名稱
● 重點:渲染檢視
- 觀察到返回一個模型物件,根據方法呼叫的先後順序,先呼叫了view.render(mv.getModelInternal(), request, response);的mv.getModelInternal()方法,需要重新深入一次
● 在渲染檢視render方法內部,觀察到mergedModel,觀察它的值:
{msg=你好,easyMVC}
- 非重點:預響應