當前位置:
首頁 > 最新 > 深入底層,仿SpringMVC自己寫框架

深入底層,仿SpringMVC自己寫框架

前言:

前面的文章我們介紹過如何自己寫一個MyBatis框架:

今天我們來寫一個SpringMVC框架,相比於寫MyBatis框架,SpringMVC要簡單一些,只需要xml解析+反射就可以完成,不需要jdk動態代理。

廢話不多說,直接開始摟乾貨。

要自己寫框架,必須理解框架的底層原理和運行機制。那麼我們首先來回顧SpringMVC的實現原理。

SpringMVC實現原理:

核心組件:

1.DispatcherServlet:前端控制器,是整個流程式控制制的核心,控制其他組件的執行,統一調度,降低組件之間的耦合性,相當於總指揮。

2.Handler:處理器,完成具體業務邏輯,相當於Servlet或Action。

3.HandlerMapping:DispatcherServlet接收到請求之後,通過HandlerMapping將不同的請求分發到不同的Handler。

4.HandlerInterceptor:處理器攔截器,是一個介面,如果我們需要做一些攔截處理,可以來實現這個介面。

5.HandlerExecutionChain:處理器執行鏈,包括兩部分內容:Handler和HandlerInterceptor(系統會有一個默認的HandlerInterceptor,如果需要額外攔截處理,可以添加攔截器設置)。

6.HandlerAdapter:處理器適配器,Handler執行業務方法之前,需要進行一系列的操作包括表單數據的驗證,數據類型的轉換,將表單數據封裝到JavaBean等等,這一系列的操作,都是由HandlerAdapter來完成,DispatcherServlet通過HandlerAdapter執行不同的Handler。

7.ModelAndView:裝載了模型數據和視圖信息,作為Handler的處理結果,返回給DispatcherServlet。

8.ViewResolver:視圖解析器,DispatcherServlet通過它將邏輯視圖解析成物理視圖,最終將渲染結果響應給客戶端。

以上就是SpringMVC的核心組件。那麼這些組件之間是如何進行交互的呢?

我們來看SpringMVC的實現流程:

1.客戶端請求被DispatcherServlet(前端控制器)接收。

2.根據HandlerMapping映射到Handler。

3.生成Handler和HandlerInterceptor(如果有則生成)。

4.Handler和HandlerInterceptor以HandlerExecutionChain的形式一併返回給DispatcherServlet。

5.DispatcherServlet通過HandlerAdapter調用Handler的方法做業務邏輯處理。

6.返回一個ModelAndView對象給DispatcherServlet。

7.DispatcherServlet將獲取的ModelAndView對象傳給ViewResolver視圖解析器,將邏輯視圖解析成物理視圖View。

8.ViewResolver返回一個View給DispatcherServlet。

9.DispatcherServlet根據View進行視圖渲染(將模型數據填充到視圖中)。

10.DispatcherServlet將渲染後的視圖響應給客戶端。

通過以上的分析,大致可以將SpringMVC流程理解如下:

首先需要一個前置控制器DispatcherServlet,作為整個流程的核心,由它去調用其他組件,共同完成業務。主要組件有兩個:一是Controller,調用其業務方法Method,執行業務邏輯。二是ViewResolver視圖解析器,將業務方法的返回值解析為物理視圖+模型數據,返回客戶端。

我們自己寫框架就按照這個思路來。

初始化工作:

1.根據Spring IOC的思路,需要將參與業務的對象全部創建並保存,供流程調用。所以首先我們需要創建Controller對象,HTTP請求是通過註解找到對應的Controller對象,所以我們需要將所有的Controller與其註解建立關聯,很顯然,使用key-value結構的Map集合來保存最合適不過了,這樣就模擬了IOC容器。

2.Controller的Method也是通過註解與HTTP請求映射的,同樣的,我們需要將所有的Method與其註解建立關聯,HTTP直接通過註解的值找到對應的Method,這裡也用Map集合保存。

3.實例化視圖解析器。

初始化工作完成,接下來處理HTTP請求,業務流程如下:

1.DispatcherServlet接收請求,通過映射從IOC容器中獲取對應的Controller對象。

2.根據映射獲取Controller對象對應的Method。

3.調用Method,獲取返回值。

4.將返回值傳給視圖解析器,返回物理視圖。

5.完成頁面跳轉。

思路捋清楚了,接下來開始寫代碼,我們需要創建以下類:

1.MyDispatcherServlet:模擬DispatcherServlet。

2.MyController:模擬Controller註解。

3.MyRequestMapping:模擬RequestMapping註解。

4.MyViewResolver:模擬ViewResolver視圖解析器。

創建MyDispatcherServlet,init方法完成初始化:

1.將Controller與註解進行關聯,保存到iocContainer中。

哪些Controller是需要添加到iocContainer中的?

必須同時滿足兩點:

1.springmvc.xml中配置掃描的類。

2.類定義處添加了註解。

注意這兩點必須同時滿足。

代碼思路:

(1)解析springmvc.xml。

(2)獲取component-scan標籤配置的包下的所有類。

(3)判斷若這些類添加了@MyController註解,則創建實例對象,並且保存到iocContainer。

(4)@MyRequestMapping的值為鍵,Controller對象為值。

2.將Controller中的Method與註解進行關聯,保存到handlerMapping中。

代碼思路:

(1)遍歷iocContainer中的Controller實例對象。

(2)遍歷每一個Controller對象的Method。

(3)判斷Method是否添加了@MyRequestMapping註解,若添加,則進行映射並保存。

(4)保存到handlerMapping中,@MyRequestMapping的值為鍵,Method為值。

3.實例化ViewResolver。

代碼思路:

(1)解析springmvc.xml。

(2)根據bean標籤的class屬性獲取需要實例化的MyViewResolver。

(3)使用反射創建實例化對象,同時獲取prefix和suffix屬性,以及setter方法。

(4)使用反射調用setter方法給屬性賦值,完成MyViewResolver的實例化。

doPost方法處理HTTP請求:

1.解析HTTP,分別得到Controller和Method對應的uri。

2.通過uri分別在iocContainer和handlerMapping中獲取對應的Controller以及Method。

3.使用反射調用Method,執行業務方法,獲取結果。

4.結果傳給MyViewResolver進行解析,返回真正的物理視圖(JSP頁面)。

5.完成JSP的頁面跳轉。

代碼:

1.創建MyController註解,作用目標為類。

2.創建MyRequestMapping註解,作用目標為類和方法。

3.創建MyDispatcherServlet,核心控制器,init完成初始化工作,doPost處理HTTP請求。

4.創建視圖解析器MyViewResolver。

5.創建TestController,處理業務請求。

6.測試。

跳轉index.jsp,同時控制台列印業務日誌,訪問成功。

源碼:

github

https://github.com/southwind9801/SpringMVCImitate.git

專業 熱愛 專註

致力於最高效的Java學習

Java大聯盟


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java大聯盟 的精彩文章:

TAG:Java大聯盟 |