閱讀目錄
- Spring MVC概述
- Spring MVC架構的特點
- Spring MVC工作原理
Spring的web架構圍繞
DispatcherServlet
設計,
DispatcherServlet
的作用是将請求分發到不同的處理器。
Spring的web架構包括可配置的處理器(handler)映射、視圖(view)解析、本地化(local)解析、 主題(theme)解析以及對檔案上傳的支援。
Spring的Web架構中預設的處理器是org.springframework.web.servlet.mvc.
Controller
接口
public interface Controller {
/**
* Process the request and return a ModelAndView object which the DispatcherServlet
* will render. A {@code null} return value is not an error: it indicates that
* this object completed request processing itself and that there is therefore no
* ModelAndView to render.
* @param request current HTTP request
* @param response current HTTP response
* @return a ModelAndView to render, or {@code null} if handled directly
* @throws Exception in case of errors
*/
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
可以通過實作這個接口來建立自己的控制器(也可以稱之為處理器),但是更推薦繼承Spring提供的一系列控制器, 比如
AbstractController
、
AbstractCommandController
和
SimpleFormController
。
注意,需要選擇正确的基類:如果沒有表單,就不需要一個FormController, 這是和Struts的一個主要差別。
Spring Web MVC允許使用任何對象作為指令對象(或表單對象),不必實作某個特定于架構的接口或從某個基類繼承。
Spring的資料綁定相當靈活,例如,它認為類型不比對這樣的錯誤應該是應用級的驗證錯誤,而不是系統錯誤,是以你不需要為了保證表單内容的正确送出,而重複定義一個和業務對象有相同屬性的表單對象來處理簡單的無類型字元串或者對字元串進行轉換。這也是和Struts相比的另一個重要差別,Struts是圍繞 Action和ActionForm等基類建構的。
和WebWork相比,Spring将對象細分成更多不同的角色:控制器(
Controller
)、可選的指令對象(Command Object)或表單對象(Form Object), 以及傳遞到視圖的模型(Model)。
模型不僅包含指令對象或表單對象,而且也可以包含任何引用資料。 相比之下,WebWork的
Action
将所有的這些角色都合并在一個單獨的對象裡。 雖然WebWork的确允許在表單中使用現有的業務對象,但是必須把它們定義成相應的
Action
類的bean屬性。
更重要的是,在進行視圖層(View)運算和表單指派時,WebWork使用的是同一個處理請求的
Action
執行個體。是以,引用資料也需要被定義成
Action
的bean屬性。這樣一個對象就承擔了太多的角色(當然,對于這個觀點仍有争議)。
Spring的視圖解析相當靈活。一個控制器甚至可以直接向response輸出一個視圖 (此時控制器傳回ModelAndView的值必須是null)。
在一般的情況下,一個ModelAndView 執行個體包含一個視圖名字和一個類型為
Map
的model, 一個model是一些以bean的名字為key,以bean對象(可以是指令或form,也可以是其他的JavaBean) 為value的鍵值對。
對視圖名稱的解析處理也是高度可配置的,可以通過bean的名字、屬性檔案或者自定義的
ViewResolver
實作來進行解析。
實際上基于
Map
的model(也就是MVC中的M)是高度抽象的,适用于各種表現層技術。 也就是說,任何表現層都可以直接和Spring內建,無論是JSP、Velocity還是其它表現層技術。
Map model可以被轉換成合适的格式,比如JSP request attribute或者Velocity template model。
- 清晰的角色劃分:控制器(controller)、驗證器(validator)、 指令對象(command object)、表單對象(form object)、模型對象(model object)、 Servlet分發器(
)、 處理器映射(handler mapping)、視圖解析器(view resolver)等等。 每一個角色都可以由一個專門的對象來實作。DispatcherServlet
- 強大而直接的配置方式:将架構類和應用程式類都能作為JavaBean配置,支援跨多個context的引用,例如,在web控制器中對業務對象和驗證器(validator)的引用。
- 可适配、非侵入:可以根據不同的應用場景,選擇合适的控制器子類 (simple型、command型、form型、wizard型、multi-action型或者自定義),而不是從單一控制器 (比如Action/ActionForm)繼承。
- 可重用的業務代碼:可以使用現有的業務對象作為指令或表單對象,而不需要去擴充某個特定架構的基類。
- 可定制的綁定(binding) 和驗證(validation):比如将類型不比對作為應用級的驗證錯誤, 這可以儲存錯誤的值。再比如本地化的日期和數字綁定等等。在其他某些架構中,你隻能使用字元串表單對象, 需要手動解析它并轉換到業務對象。
- 可定制的handler mapping和view resolution:Spring提供從最簡單的URL映射, 到複雜的、專用的定制政策。與某些web MVC架構強制開發人員使用單一特定技術相比,Spring顯得更加靈活。
- 靈活的model轉換:在Springweb架構中,使用基于
的 鍵/值對來達到輕易地與各種視圖技術的內建。Map
- 可定制的本地化和主題(theme)解析:支援在JSP中可選擇地使用Spring标簽庫、支援JSTL、支援Velocity(不需要額外的中間層)等等。
- 簡單而強大的JSP标簽庫(Spring Tag Library):支援包括諸如資料綁定和主題(theme) 之類的許多功能。它提供在标記方面的最大靈活性。
- JSP表單标簽庫:在Spring2.0中引入的表單标簽庫,使得在JSP中編寫 表單更加容易。
- Spring Bean的生命周期可以被限制在目前的HTTP Request或者HTTP
。 準确的說,這并非Spring MVC架構本身特性,而應歸屬于Sping MVC使用的WebApplicationContext容器。Session
對Spring MVC的介紹參考自官方文檔:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html
Spring MVC 分離了控制器、模型對象、分派器以及處理程式對象的角色,這種分離讓它們更容易進行定制。
Spring的MVC架構主要由DispatcherServlet、處理器映射、處理器(控制器)、視圖解析器、視圖組成。

Spring MVC接口解釋
- DispatcherServlet:
Spring提供的前端控制器,所有的請求都有經過它來統一分發。在DispatcherServlet将請求分發給Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具體的Controller。
- HandlerMapping:
能夠完成客戶請求到Controller映射。
- Controller:
需要為并發使用者處理上述請求,是以實作Controller接口時,必須保證線程安全并且可重用。
Controller将處理使用者請求,這和Struts Action扮演的角色是一緻的。一旦Controller處理完使用者請求,則傳回ModelAndView對象給DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和視圖(View)。
從宏觀角度考慮,DispatcherServlet是整個Web應用的控制器;從微觀考慮,Controller是單個Http請求處理過程中的控制器,而ModelAndView是Http請求過程中傳回的模型(Model)和視圖(View)。
- ViewResolver:
Spring提供的視圖解析器(ViewResolver)在Web應用中查找View對象,進而将相應結果渲染給客戶。
Spring MVC運作原理
- 用戶端請求送出到DispatcherServlet
- 由DispatcherServlet控制器查詢一個或多個HandlerMapping,找到處理請求的Controller
- DispatcherServlet将請求送出到Controller
- Controller調用業務邏輯處理後,傳回ModelAndView
- DispatcherServlet查詢一個或多個ViewResoler視圖解析器,找到ModelAndView指定的視圖
- 視圖負責将結果顯示到用戶端
DispatcherServlet是整個Spring MVC的核心。它負責接收HTTP請求組織協調Spring MVC的各個組成部分。其主要工作有以下三項:
- 截獲符合特定格式的URL請求。
- 初始化DispatcherServlet上下文對應的WebApplicationContext,并将其與業務層、持久化層的WebApplicationContext建立關聯。
- 初始化Spring MVC的各個組成元件,并裝配到DispatcherServlet中。
Spring MVC與Structs2的差異
- Struts2是類級别的攔截, 一個類對應一個request上下文,Spring MVC是方法級别的攔截,一個方法對應一個request上下文,而方法同時又跟一個url對應。是以說從架構本身上Spring MVC就容易實作Restful URL,而Struts2的架構實作起來要費勁,因為Struts2中Action的一個方法可以對應一個url,而其類屬性卻被所有方法共享,這也就無法用注解或其他方式辨別其所屬方法了。
- 由上邊原因,Spring MVC的方法之間基本上獨立的,獨享request response資料,請求資料通過參數擷取,處理結果通過ModelMap交回給架構,方法之間不共享變量,而Struts2搞的就比較亂,雖然方法之間也是獨立的,但其所有Action變量是共享的,這不會影響程式運作,卻給我們編碼讀程式時帶來麻煩,每次來了請求就建立一個Action,一個Action對象對應一個request上下文。
- 由于Struts2需要針對每個request進行封裝,把request,session等servlet生命周期的變量封裝成一個一個Map,供給每個Action使用,并保證線程安全,是以在原則上,是比較耗費記憶體的。
- 攔截器實作機制上,Struts2有以自己的interceptor機制,Spring MVC用的是獨立的AOP方式,這樣導緻Struts2的配置檔案量還是比Spring MVC大。
- Spring MVC的入口是servlet,而Struts2是filter(這裡要指出,filter和servlet是不同的,以前認為filter是servlet的一種特殊),這就導緻了二者的機制不同,這裡就牽涉到servlet和filter的差別了。
- Spring MVC內建了Ajax,使用非常友善,隻需一個注解@ResponseBody就可以實作,然後直接傳回響應文本即可,而Struts2攔截器內建了Ajax,在Action中處理時一般必須安裝插件或者自己寫代碼內建進去,使用起來也相對不友善。
- Spring MVC驗證支援JSR303,處理起來相對更加靈活友善,而Struts2驗證比較繁瑣,感覺太煩亂。
- Spring MVC和Spring是無縫的。從這個項目的管理和安全上也比Struts2高(當然Struts2也可以通過不同的目錄結構和相關配置做到Spring MVC一樣的效果,但是需要xml配置的地方不少)。
- 設計思想上,Struts2更加符合OOP的程式設計思想, Spring MVC就比較謹慎,在servlet上擴充。
- Spring MVC開發效率和性能高于Struts2。
- Spring MVC可以認為已經100%零配置。
DispatcherServlet
DispatcherServlet
Controller
public interface Controller {
/**
* Process the request and return a ModelAndView object which the DispatcherServlet
* will render. A {@code null} return value is not an error: it indicates that
* this object completed request processing itself and that there is therefore no
* ModelAndView to render.
* @param request current HTTP request
* @param response current HTTP response
* @return a ModelAndView to render, or {@code null} if handled directly
* @throws Exception in case of errors
*/
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
AbstractController
AbstractCommandController
SimpleFormController
Controller
Action
Action
Action
Action
Map
ViewResolver
Map
-
DispatcherServlet
-
Map
-
Session
