SpringMVC
Spring Web MVC 是最原始的Web框架督函,在最原始的Servlet的基礎(chǔ)上構(gòu)建的
兄弟 Spring Web Flux 非阻塞的異步的
DispatcherServlet
一個(gè)繼承源于Servlet的類激挪,是一個(gè)前置控制器,起請(qǐng)求分發(fā)的作用
所有的請(qǐng)求都會(huì)委托給DispatchServlet宛篇,既然是Servlet薄湿,就需要
被定義和映射到Servlet容器中,使用Java configuration 或者web.xml
SpringMVC 原理探究
繼承關(guān)系 DispatchServlet → FrameworkServlet → HttpServletBean → HttpServlet
HttpServlet 是原生的Servlet吆倦,有個(gè)service方法炉奴,所以我們?nèi)ニ淖宇愔姓襰ervice方法,在HttpServletBean中沒找到service的實(shí)現(xiàn)方法瞻赶,繼續(xù)尋找子類FrameworkServlet派任,找到了
可以看到掌逛,先調(diào)用了HttpMethod的.resolve方法司倚,打開HttpMethod是個(gè)啥子
沒錯(cuò),是個(gè)枚舉动知,這個(gè)是springmvc提供的HTTP請(qǐng)求方法
resolve其實(shí)就是將客戶端請(qǐng)求字符串封裝成HttpMethod的枚舉
之后的判斷,根據(jù)請(qǐng)求方法盒粮,如果是PATCH或者是空,直接走processRequest(request, response)方法妒穴,如果是其他的標(biāo)準(zhǔn)方法摊崭,會(huì)去調(diào)用父類的service方法,然而父類的service方法會(huì)判斷請(qǐng)求方法呢簸,走對(duì)應(yīng)的方法阔墩,比如說(shuō)GET走doGet方法
在FrameworkServlet的doGet、doPost等標(biāo)準(zhǔn)請(qǐng)求中,總是在調(diào)用processRequest方法伞芹,我們來(lái)看看這個(gè)方法
主要調(diào)用了doService唱较,而FrameworkServlet類的doService是個(gè)抽象方法,所以去子類看看
doService又去調(diào)用doDispatch方法
先檢查是否為多媒體請(qǐng)求胸遇,然后去getHandler
handlerMappings可以調(diào)試發(fā)現(xiàn)汉形,有兩個(gè)
遍歷這兩個(gè)Map倍阐,去嘗試尋找符合request的Controller逗威,找到之后,將Controller和他對(duì)應(yīng)的攔截器封裝到HandlerExecutionChain里面然后將對(duì)象返回給doDispatch方法
之后
獲取HandlerAdapter概耻,
根據(jù)controller對(duì)象去找到合適的適配器鞠柄,可以發(fā)現(xiàn)和HandlerMapping如出一轍
可以通過(guò)調(diào)試找到
HttpRequestHandlerAdapter
SimpleControllerHandlerAdapterXML配置的適配器
RequestMappingHandlerAdapter注解配置的適配器
代碼繼續(xù)往下走applyPreHandle
有攔截器的話走攔截器嫉柴,因?yàn)橛袛r截器的話,在的doDispatch那里直接return了
沒有攔截器的話
執(zhí)行handle期奔,其實(shí)就是執(zhí)行Controller的方法危尿,處理業(yè)務(wù)邏輯,返回一個(gè)ViewAndModel 對(duì)象
在調(diào)用processDispatchResult這里將request肺孤,response济欢,controller和攔截器,ViewAndModel等都給這個(gè)方法
我們來(lái)看這個(gè)方法茫叭,處理之前的判斷傳過(guò)來(lái)的數(shù)據(jù)是否可用
它主要去調(diào)用了render方法
先設(shè)置了本地化半等,之后主要調(diào)用resolveViewName方法
看看,和HandlerMappings莽囤、HandlerAdapter也是一樣的切距,在viewResolvers中去尋找合適的視圖返回,其中帶著本地參數(shù),為了國(guó)際化的頁(yè)面北秽,話說(shuō)回來(lái)狼牺,render方法獲取到View對(duì)象后
調(diào)用了view的render方法,其中調(diào)用了mv.getModelInternal()
其實(shí) 就是把Model的數(shù)據(jù)(是個(gè)Map)給視圖掠归,讓視圖去把map里面的數(shù)據(jù)一個(gè)一個(gè)的選詞填空的填上悄泥,
View是個(gè)接口,我們來(lái)看看實(shí)現(xiàn)類
我們以Thymeleaf為例子
是View的實(shí)現(xiàn)類將最后填空的作業(yè)用原生的Response響應(yīng)給客戶端的厨相,在相應(yīng)html字符串的這里鸥鹉,dispatchservlet沒有參與
來(lái)張圖補(bǔ)腦
[百度]?最后一張圖來(lái)源于百度