SpringMVC
Spring Web MVC 是最原始的Web框架,在最原始的Servlet的基礎(chǔ)上構(gòu)建的
兄弟 Spring Web Flux 非阻塞的異步的
DispatcherServlet
一個繼承源于Servlet的類,是一個前置控制器,起請求分發(fā)的作用
所有的請求都會委托給DispatchServlet,既然是Servlet,就需要
被定義和映射到Servlet容器中,使用Java configuration 或者web.xml
SpringMVC 原理探究
繼承關(guān)系 DispatchServlet → FrameworkServlet → HttpServletBean → HttpServlet
HttpServlet 是原生的Servlet,有個service方法,所以我們?nèi)ニ淖宇愔姓襰ervice方法,在HttpServletBean中沒找到service的實現(xiàn)方法,繼續(xù)尋找子類FrameworkServlet,找到了

可以看到,先調(diào)用了HttpMethod的.resolve方法,打開HttpMethod是個啥子

沒錯,是個枚舉,這個是springmvc提供的HTTP請求方法
resolve其實就是將客戶端請求字符串封裝成HttpMethod的枚舉
之后的判斷,根據(jù)請求方法,如果是PATCH或者是空,直接走processRequest(request, response)方法,如果是其他的標準方法,會去調(diào)用父類的service方法,然而父類的service方法會判斷請求方法,走對應(yīng)的方法,比如說GET走doGet方法


在FrameworkServlet的doGet、doPost等標準請求中,總是在調(diào)用processRequest方法,我們來看看這個方法

主要調(diào)用了doService,而FrameworkServlet類的doService是個抽象方法,所以去子類看看

doService又去調(diào)用doDispatch方法

先檢查是否為多媒體請求,然后去getHandler

handlerMappings可以調(diào)試發(fā)現(xiàn),有兩個
遍歷這兩個Map,去嘗試尋找符合request的Controller,找到之后,將Controller和他對應(yīng)的攔截器封裝到HandlerExecutionChain里面然后將對象返回給doDispatch方法

之后

獲取HandlerAdapter,

根據(jù)controller對象去找到合適的適配器,可以發(fā)現(xiàn)和HandlerMapping如出一轍
可以通過調(diào)試找到
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapterXML配置的適配器
RequestMappingHandlerAdapter注解配置的適配器

代碼繼續(xù)往下走applyPreHandle

有攔截器的話走攔截器,因為有攔截器的話,在的doDispatch那里直接return了
沒有攔截器的話

執(zhí)行handle,其實就是執(zhí)行Controller的方法,處理業(yè)務(wù)邏輯,返回一個ViewAndModel 對象

在調(diào)用processDispatchResult這里將request,response,controller和攔截器,ViewAndModel等都給這個方法
我們來看這個方法,處理之前的判斷傳過來的數(shù)據(jù)是否可用

它主要去調(diào)用了render方法

先設(shè)置了本地化,之后主要調(diào)用resolveViewName方法

看看,和HandlerMappings、HandlerAdapter也是一樣的,在viewResolvers中去尋找合適的視圖返回,其中帶著本地參數(shù),為了國際化的頁面,話說回來,render方法獲取到View對象后

調(diào)用了view的render方法,其中調(diào)用了mv.getModelInternal()

其實 就是把Model的數(shù)據(jù)(是個Map)給視圖,讓視圖去把map里面的數(shù)據(jù)一個一個的選詞填空的填上,
View是個接口,我們來看看實現(xiàn)類

我們以Thymeleaf為例子
是View的實現(xiàn)類將最后填空的作業(yè)用原生的Response響應(yīng)給客戶端的,在相應(yīng)html字符串的這里,dispatchservlet沒有參與

來張圖補腦

[百度]?最后一張圖來源于百度