1. 程式人生 > >手寫一個迷你版Spring MVC框架

手寫一個迷你版Spring MVC框架

前期準備

我這裡要寫的是一個迷你版的Spring MVC,我將在一個乾淨的web工程開始開發,不引入Spring,完全通過JDK來實現。

我們先來看一眼工程:

640

工程程式碼結構

第一:在annotation包下,我將提供自定義的註解,為了方便理解,就和Spring MVC保持一致。

第二:為了模擬Spring MVC的方法呼叫鏈,我這裡提供Controller/Service/Dao層進行測試。

第三:提供自己的DispatcherServlet完成核心處理邏輯。

關於自定義註解

JDK提供了幾個元註解,比如:

  • @Documented : JavaDoc文件

  • @Target:標誌此註解可以修飾在哪些地方,類,成員變數,方法...

  • @Retention:Annotation的生命週期,一般情況下,我們自定義註解的話,顯然需要在執行期獲取註解的一些資訊。

看一下我這邊的自定義註解:

640

模擬Spring MVC的@Controller註解

640

@Qualifier提供依賴注入

640

@RequestMapping提供URL地址處理對映

640

Dao層註解

640

Service層註解

編寫核心控制器:DispatcherServlet

在Spring MVC中,DispatcherServlet是核心,下面我們來實現它。首先來說,Spring MVC中的DispatcherServlet說到底,還是HttpServlet的子類,因此我這邊自己的DispatcherSerlvet需要extends HttpServlet。

pom.xml:

640

提供servlet依賴

看DispatcherServlet的定義:

640

DispatcherServlet

@WebServlet是什麼?

其實,以前我們定義一個Servlet,需要在web.xml中去配置,不過在Servlet3.0後出現了基於註解的Servlet。

仔細觀察,你會發現,這個DispatcherServlet是自啟動,而且傳入了一個引數。

要知道,在Spring MVC中,要想基於註解,需要在配置中指明掃描的包路徑,就像這個樣子:

<context:component-scan base-package="com.zfz.myspringmvc">

</context:component-scan>

為了方便,我這裡就通過初始化引數直接將需要掃描的基包路徑傳入。

init初始化處理:

640

init()

其實,在init中,我們主要是完成了什麼呢?

第一:我們應該去掃描基包下的類,得到資訊A。

第二:對於@Controller/@Service/@Repository註解而言,我們需要拿到對應的名稱,並初始化它們修飾的類,形成對映關係B。

第三:我們還得掃描類中的欄位,如果發現有@Qualifier的話,我們需要完成注入。

第四:我們還需要掃描@RequestMapping,完成URL到某一個Controller的某一個方法上的對映關係C。

其實,Spring MVC的處理流程,就是類似這樣的!

掃描基包:

640

掃描基包

注意,基包是X.Y.Z的形式,而URL是X/Y/Z的形式,需要轉換。

例項化:

640

例項化

從這裡你可以看出,我們完成了被註解標註的類的例項化,以及和註解名稱的對映。

依賴注入:

640

依賴注入

以前,我們總是說Spring IOC,上面不就是在做這個事情麼?

URL對映處理:

640

URL對映處理

URL,我們需要提取出來,對映到Controller的Method上。

doGet/doPost:

640

doGet/doPost

在doPost方法中,非常簡單,我們只需要提取出URL,通過URL對映到Method上,然後通過反射的方式進行呼叫即可。

Make it run!

Controller層:

640

UserController

Service層:

640

UserService

640

UserServiceImpl

Dao層:

640

UserDao

640

UserDaoImpl

執行結果:

640

result

OK,到這裡,一個迷你版的Spring MVC就開發完成了。

PS:如果覺得我的分享不錯,歡迎大家隨手點贊、轉發。

Java團長

專注於Java乾貨分享

640

掃描上方二維碼獲取更多Java乾貨