springMVC的核心源碼分析和它的工作機制


springMVC是一個基於spring的web框架,也可以說是spring的一個子容器,我們來談談sringMVC

    一、springMVC的請求處理流程

   首先我們來一張很形象的簡單的流程圖

  

 

 1、DispatherServlet顧名思義一個調度的Servlet,是一個front-controller(前端控制器),也可以說是springMVC的C位哈哈,負責接受客戶端的request,並將這些request分配給對應的處理組件

 2、HandlerMapping顧名思義映射處理器,是一個url和controller的映射組件,DispatcherServlet攔截request的請求然后對請求URL進行解析得到URI(資源標識符),接着根據該URI調用HandlerMapping獲得Handler配置的所有相關對象(包括Handler對象以及Handler對象對應的攔截器)最后封裝到HandlerExecutionChain對象中返回

3.DispatcherServlet 根據獲得的Handler,選擇一個合適的HandlerAdapter。(附注:如果成功獲得HandlerAdapter后,此時將開始執行攔截器的preHandler(…)方法)

4.提取Request中的模型數據,填充Handler入參,開始執行Handler(Controller)。 在填充Handler的入參過程中,根據你的配置,Spring將幫你做一些額外的工作:

   HttpMessageConveter: 將請求消息(如Json、xml等數據)轉換成一個對象,將對象轉換為指定的響應信息

   數據轉換:對請求消息進行數據轉換。如String轉換成Integer、Double等

   數據根式化:對請求消息進行數據格式化。 如將字符串轉換成格式化數字或格式化日期等

   數據驗證: 驗證數據的有效性(長度、格式等),驗證結果存儲到BindingResult或Error中

5.Handler執行完成后,向DispatcherServlet 返回一個ModelAndView對象;

6.根據返回的ModelAndView,選擇一個適合的ViewResolver(必須是已經注冊到Spring容器中的ViewResolver)返回給DispatcherServlet ;

7.ViewResolver 結合Model和View,來渲染視圖

8.將渲染結果返回給客戶端。

接下來我們根據核心源碼來分析它里面的結構

  首先我們了解springMVC這個框架 它本身提供的這些默認的組件我們可以在DispatcherServlet.properties這個配置文件可以看到

接下倆我們可以看一下Dispatcher類的層次結構

我們直接把重點放在DispatcherServlet(front-controller)

從流程圖可以看出,用戶的請求最先到達就是DispatcherServlet,它是springmvc的核心,可以把它叫做中央處理器,因此我們分析源碼之前,先看看他是什么樣的流程,通過源碼可以看出,它是繼承FrameworkServlet,它也是springmvc提供的類,繼續往下繼承關系看,FrameworkServlet繼承HttpServletBean,她是spring提供的類,最終直到到它繼承HttpServlet

我們接着看這個關系圖,它是不是實現了這個servlet接口,既然它是servlet,那么它肯定有一個service方法(servlet最核心的方法),我么看這個方法在哪里實現的,一個個看,發現HttpServletBean並沒有,再看FrameworkServlet發現有了,因此spring實現這個serivice方法在這里實現的

這個方法的作用的就是得到客戶端的請求,然后判斷這個請求是不是PATCH請求方式,如果不是就調用父類(httpServlet)中的service方法,我們調用父類這個service方法其實實際是調用該類的

doget方法或者dopost方法等等,拿到不同的請求方式處理不同的業務,我們以get方式為例吧

拿到這個方法,我們進入到processRequest方法

以上其他代碼我們不用細看,是一些關於控制器的代碼,我們直接進入doservice方法

 

我們可以看到我們跳到DispatcherServlet這個類里面來了,其實doSerivice可以猜到被子類各種重寫哈哈,話不多講直接進入doDispatch這個方法

 

 

前面的那些都不是核心代碼,我們進入到這個doDispatcher方法才算進入springmvc的核心代碼區域,由源碼可得:它首先主要創建一個ModelAndView對象 = null,首先判斷當前請求是不是

二進制的請求processedRequest = this.checkMultipart(request),然后我們再看底下代碼

mappedHandler = this.getHandler(processedRequest);就是根據當前請求去拿一個handler(控制器),這個handler其實就是我們的控制器包括我們處理業務邏輯的controller,進入到這個方法的源碼

由流程圖可知,發送清求到控制器,控制器第二個節點就是發送第二個請求就是去拿Handler,因此可知這里才是最核心代碼。由圖可知他取Handler最終要去找HandlerMapping,然后他再去拿一個Handler。那么為什么要去找HandlerMapping去要一個Handler呢?首先我們在配置控制器的時候有兩種方式1.xml方式,2.注解的方式。因此spring源碼他給我們不止一種控制器 。因為兩種方式控制器 。因此spring並不知道我們使用的事哪一種控制器。因為兩種控制器,spring去底層去找的控制的實現方式是不一樣的。因此這就是為什么第二步他要去找Handler(控制器)的了。但是Handler怎么找的到呢?就是通過HandlerMapping這樣一個處理器映射器。如代碼可知他首先是判斷當前HandlerMappers是否為空:this.handlerMappings

由此可看當前HandlerMappers有兩個對象也就是兩個Handler。因此可知上面說的,spring不止一個控制器;相當於他來這里面找他所要的控制器。一個是xml對應的,一個是注解對應的注:因此這里主要以xml方式進行講解。注解形式其實一樣,只不過去匹配注解對象的HandlerMapping以及HandlerAdapter).

那么接下來他會怎么處理呢?由源碼得知,spring首先是遍歷HandlerMappers,怎么遍歷呢?他會問當前數組中有沒有我這控制器。也就是代碼中的mapping對應的是當前控制器

找到之后,他返回的是一個HandlerExecutionChain類型的Handle,這里面封裝了一個BeanController,也就是我們自己的創建controlller,如果有配置攔截器我們還會封裝一個攔截器(interceptor)

因此到這里我們就拿到了對應的也是最合適的Handler,然后返回給DispatcherServlet

然后到第二個方法: 

HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());

獲取控制器的適配器。也就是我們之前拿到了控制器,接下來要去執行控制器,也就是拿到控制器適配器中執行控制器。這里為什么要獲取適配器呢?因為跟控制器映射器(也就是配置方式)一樣。
你就有不同的適配器。因此適配器也不是一個。跟我們上面Handler原理一樣。

接下來就是適配器去執行Handler

 mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

如果你有ModelAndView,就返回一個ModelAndView.然后返回給試圖對象,然后把視圖對象交給視圖解析器,去渲染,最后響應給用戶。

因此總結,spring提供了兩種HandlerMapping以及三種HandlerAdapter
而它是怎么獲取的呢springMVC初始化時就加載實例化,獲取這些對象。他們是被配置在spring的SpringwebMVC架包的servlet架包中的DispatcherServlet.properties配置文件中

 
 
        
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM