Spring MVC調度流程

一、Spring MVC的由來

 在最早期WEB系統有前端到後端是:

請求+JSP+Java Bean + 數據庫 的模式,這種JSP和Java Bean前後端耦合在一起會帶來很多麻煩,這種模式下JSP身兼多職,既要負責視圖層的數據展示,又要負責業務流程控制,結構較爲混亂,也不是我們所希望的松耦合架構,如下:

後來被Servlet+JSP+Java Bean+數據庫 的模式取代,多了一個Serverlet組件,用戶的請求先到Servlet,Servlet相當於一個控制器,它來調度Java Bean以及讀取數據庫,最後把結果放到JSP進行展示。這時Servlet就是Controller,Java Bean就是Model,JSP就是View,這時前端和後端是解耦的,這時MVC分層架構的由來。當業務流程比較複雜的時候,就需要把業務流程控制交給專門的控制器,JSP只專注於視圖的渲染展現即可。但是隨着移動端手機、平板、各種終端的請求增加,這種模式的短板也暴露出來,那就是JSP適用於WEB端,但是不支持移動端。

爲了兼顧各種終端,Spring MVC框架在上面的基礎上進行了調整。它將原來的Model層又拆分成Service層和Dao層,如下:

Spring MVC是Spring家族中應用於Web應用的一個模塊,是Spring提供的一個基於MVC設計模式的Web開發框架,可以將它理解爲Servlet。在MVC模式中,Spring MVC作爲控制器(Controller)來建立模型與視圖的數據交互,是結構最清晰的JSP Model2實現,可以說是一個典型的MVC框架。

除此之外,Spring MVC框架採用松耦合、可插拔的組件結構,具有高度可配置性,比起其他的MVC框架更具有擴展性和靈活性。並且它本身就是Spring家族的一部分,與Spring框架整合更是天衣無縫。

在Spring MVC框架中,Controller替換Servlet來擔負控制器的職責。Controller接收請求,調用相應的Model進行處理,Model處理完之後將結果返回給Controller,Conreoller再指派相應的View對處理結果進行渲染,最終響應給客戶端進行展示。
 

SpringMVC 是基於 Spring 框架派生 Web 框架, 所以它天然就可以十分方便 整合 Spring 框架中,而 Spring 整合 Struts2 還是比較繁複的(另外Struts2 還爆出了漏洞問題)。

Spring MVC 開始就定位爲鬆散的組合,展示給用戶的視圖(View)、 控制器返回的數據模型( Model )、 定位視圖的視圖解析器(ViewResolver) 和處理適配器( HandlerAdapter )等都是獨立的,換句 話說, Spring MVC 很容易把後臺數據轉換爲各種類型的數據 ,以滿足互聯網多樣化的要求, 例如,Spring MVC 可以十分方便的轉換爲目前最常用 JSON 數據集,也可以轉換爲 PDF、Excel 和XML等。

下面我們需要研究下它的轉換流程。

 

二、Spring MVC的組件與流程

流程和組件是 SpringMVC 的核心, SpringMVC的流程是圍 DispatcherServlet 而工作的,所以 DispatcherServlet 是其最重要的內容。在DispatcherServlet的基礎上,還存在其他的組件, 掌握流程和組件就是 SpringMVC 開發的基礎。總體流程圖如下:

這個圖不知道誰畫的,畫的還挺明白我就盜過來了,不過還是要解釋一下:

圖2-1
圖2-2

首先,在Web務器啓動的過程中,如果在 Spring Boot 機制下 Spring MVC 它就開始初始化一些重要的組件,例如 DispactherServlet,RequestMappingHandlerAdapter(HandlerAdapter的實現類)等組件對象。具體的可以查看spring webmvc-xxx.jar 包的屬性文件DispatcherServlet.properties, 它定義的對象都是在 SpringMVC 開始時就初始化,並且存放在 Spring IoC容器中,如圖2-1和圖2-2。

 

我們先看一個Controller,也就是控制器:

@Controller
@RequestMapping("/home")
public class TestController {
    @RequestMapping("/test1")
    public String index_1(){
        String str = "666";
        ModelAndView mv = new ModelAndView();
        mv.setViewName("jj");
        mv.addObject("str", str);
        return str;
    }
}

@Controller註解標註這是一個控制器,@RequestMapping("/home")代表控制器和請求路徑的映射關係,會在服務啓動時就被掃描到HandlerMapping中存儲,用戶發起的請求會被DispactherServlet接收,並通過URI請求HandlerMapping返回一個HandlerExcutionChain對象,這個對象包含了處理器Handler,Handler是對控制器Controller的包裝,同時Handler還包含攔截器(interceptor)。

DispactherServlet從HandlerMapping中得到了Handler,下面就需要執行這個Handler,執行Handler由HandlerAdapter完成。爲什麼還需要一個HandlerAdapter才能執行Handler?那是因爲請求的種類的不同(有普通 HTTP 請求、WebSocket 的請求、按 BeanName 的請求),得到的Handler類型也不同,因此需要一個統一的適配器去運行HandlerExecutionChain 對象包含的Handler。

Handler在執行時會調用Controller,通過模型層獲取數據,對數據進行處理後,最後返回模型和視圖(ModelAndView )對象給DispactherServlet。(congtroller方法可能存在參數,那麼Handler就可以讀入 HTTP和上下文的相關參數,然後再傳遞給Controller方法。而在Controller方法執行完成返回後,Handler又可以通過配置信息對控制器的返回結果進行處理

DispactherServlet拿到ModelAndView 對象就會轉發給視圖解析器( ViewResolver )。上面的代碼中,我們給視圖取名爲“jj”,如果我們在配置文件中配置了視圖的前綴和後綴:

spring.mvc.view.prefix=/WEB-INF/jsp
spring.mvc.view.suffix=.jsp

那麼 ViewResolver 就會定位到視圖, 就是/WEB-INF/jsp/jj .jsp 作爲我們的視圖。

視圖解析器定位到視圖後,視圖的作用是將數據模型( Mode )渲染,這樣就能夠響應用戶的請求。這一步就是視圖將數據模型渲染( View )出來,用來展示給用戶查看。

以上就是整個springMVC的調度流程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章