前端框架不少,但沒有一個框架稱霸,後端框架如今Spring已經完成大一統.因此學習Spring是Java程序員的必修課.css
Spring 框架對於 Java 後端程序員來講再熟悉不過了,之前只知道它用的反射實現的,但瞭解以後才知道有不少巧妙的設計在裏面。若是不看 Spring 的源碼,你將會失去一次和大師學習的機會:它的代碼規範,設計思想很值得學習。咱們程序員大部分人都是野路子,不懂什麼叫代碼規範。寫了一個月的代碼,最後還得其餘老司機花3天時間重構,相信大部分老司機都很頭疼看新手的代碼。html
廢話很少說,咱們進入今天的正題,在Web應用程序設計中,MVC模式已經被普遍使用。SpringMVC以DispatcherServlet爲核心,負責協調和組織不一樣組件以完成請求處理並返回響應的工做,實現了MVC模式。想要實現本身的SpringMVC框架,須要從如下幾點入手:前端
1、瞭解 SpringMVC 運行流程及九大組件程序員
2、本身實現 SpringMVC 的功能分析web
3、手寫 SpringMVC 框架spring
1、瞭解SpringMVC運行流程及九大組件後端
一、SpringMVC 的運行流程瀏覽器
· 用戶發送請求至前端控制器DispatcherServlet前端框架
· DispatcherServlet收到請求調用HandlerMapping處理器映射器。app
· 處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(若是有則生成)一併返回給DispatcherServlet。
· DispatcherServlet經過HandlerAdapter處理器適配器調用處理器
· 執行處理器(Controller,也叫後端控制器)。
· Controller執行完成返回ModelAndView
· HandlerAdapter將controller執行結果● ModelAndView返回給DispatcherServlet
· DispatcherServlet將ModelAndView傳給● ViewReslover視圖解析器
· ViewReslover解析後返回具體View
· DispatcherServlet對View進行渲染視圖(即將模型數據填充至視圖中)。
· DispatcherServlet響應用戶。
從上面能夠看出,DispatcherServlet有接受請求,響應結果,轉發等做用。有了DispatcherServlet以後,能夠減小組件之間的耦合度。
二、SpringMVC 的九大組件
protected void initStrategies(ApplicationContext context) {
//用於處理上傳請求。處理方法是將普通的request包裝成MultipartHttpServletRequest,後者能夠直接調用getFile方法獲取File.
initMultipartResolver(context);
//SpringMVC主要有兩個地方用到了Locale:一是ViewResolver視圖解析的時候;二是用到國際化資源或者主題的時候。
initLocaleResolver(context);
//用於解析主題。SpringMVC中一個主題對應一個properties文件,裏面存放着跟當前主題相關的全部資源、
//如圖片、css樣式等。SpringMVC的主題也支持國際化,
initThemeResolver(context);
//用來查找Handler的。
initHandlerMappings(context);
//從名字上看,它就是一個適配器。Servlet須要的處理方法的結構倒是固定的,都是以request和response爲參數的方法。
//如何讓固定的Servlet處理方法調用靈活的Handler來進行處理呢?這就是HandlerAdapter要作的事情
initHandlerAdapters(context);
//其它組件都是用來幹活的。在幹活的過程當中不免會出現問題,出問題後怎麼辦呢?
//這就須要有一個專門的角色對異常狀況進行處理,在SpringMVC中就是HandlerExceptionResolver。
initHandlerExceptionResolvers(context);
//有的Handler處理完後並無設置View也沒有設置ViewName,這時就須要從request獲取ViewName了,
//如何從request中獲取ViewName就是RequestToViewNameTranslator要作的事情了。
initRequestToViewNameTranslator(context);
//ViewResolver用來將String類型的視圖名和Locale解析爲View類型的視圖。
//View是用來渲染頁面的,也就是將程序返回的參數填入模板裏,生成html(也多是其它類型)文件。
initViewResolvers(context);
//用來管理FlashMap的,FlashMap主要用在redirect重定向中傳遞參數。
initFlashMapManager(context);
}
2、本身實現 SpringMVC 功能分析
本篇文章只實現 SpringMVC 的配置加載、實例化掃描的包、HandlerMapping 的 url 映射到對應的Controller 的 method 上、異常的攔截和動態調用後返回結果輸出給瀏覽器的功能。其他 SpringMVC 功能讀者能夠嘗試本身實現。
一、讀取配置
從圖中能夠看出,SpringMVC本質上是一個Servlet,這個 Servlet 繼承自 HttpServlet。
FrameworkServlet負責初始化SpringMVC的容器,並將Spring容器設置爲父容器。由於本文只是實現SpringMVC,對於Spring容器不作過多講解(有興趣同窗能夠看看博主另外一篇文章:向spring大佬低頭--大量源碼流出解析)。
爲了讀取web.xml中的配置,咱們用到ServletConfig這個類,它表明當前Servlet在web.xml中的配置信息。經過web.xml中加載咱們本身寫的MyDispatcherServlet和讀取配置文件。
二、初始化階段
在上文中,咱們知道了DispatcherServlet的initStrategies方法會初始化9大組件,可是本文將實現一些SpringMVC的最基本的組件而不是所有,按順序包括:
· 加載配置文件
· 掃描用戶配置包下面全部的類
· 拿到掃描到的類,經過反射機制,實例化。而且放到ioc容器中(Map的鍵值對 beanName-bean) beanName默認是首字母小寫
· 初始化HandlerMapping,這裏其實就是把url和method對應起來放在一個k-v的Map中,在運行階段取出
三、運行階段
每一次請求將會調用doGet或doPost方法,因此統一運行階段都放在doDispatch方法裏處理,它會根據url請求去HandlerMapping中匹配到對應的Method,而後利用反射機制調用Controller中的url對應的方法,並獲得結果返回。按順序包括如下功能:
· 異常的攔截
· 獲取請求傳入的參數並處理參數
· 經過初始化好的handlerMapping中拿出url對應的方法名,反射調用
3、手寫 SpringMVC 框架
工程文件及目錄:
首先,新建一個maven項目,在pom.xml中導入如下依賴。爲了方便,博主直接導入了Springboot的web包,裏面有咱們須要的全部web開發的東西:
接着,咱們在WEB-INF下建立一個web.xml,以下配置:
application.properties文件中只是配置要掃描的包到SpringMVC容器中。
scanPackage=com.liugh.core
建立本身的Controller註解,它只能標註在類上面:
RequestMapping註解,能夠在類和方法上:
RequestParam註解,只能註解在參數上
而後建立MyDispatcherServlet這個類,去繼承HttpServlet,重寫init方法、doGet、doPost方法,以及加上咱們第二步分析時要實現的功能:
這裏咱們就開發完了本身的SpringMVC,如今咱們測試一下:
訪問http://localhost:8080/liughMVC/test/doTest?param=liugh以下:
訪問一個不存在的試試:
到這裏咱們就大功告成了!