springMVC4(7)模型視圖方法源代碼綜合分析

在完整web開發中。springMVC主要充當了控制層的角色。它接受視圖層的請求。獲取視圖層請求數據,再對數據進行業務邏輯處理。而後封裝成視圖層需要的模型數據,再將數據導向到jsp等視圖界面。
在前面,咱們經過對@RequestMapping和方法入參綁定的分析,完畢了視圖層->控制層的數據交接,而後業務邏輯處理主要由Service層進行。那麼接下來很是關鍵的就是,怎樣將視圖數據導向到特定的視圖中。html

普遍意義上,視圖,並非是單指前端界面如jsp\html等。咱們可能需要給安卓、IOS等寫後臺接口、因先後端分離而放棄視圖界面導向如對前端ajax請求的純數據流輸出等。前端

這時,咱們的視圖可以爲json視圖、xml視圖、乃至PDF視圖、Excel視圖等java

springMVC爲咱們提供了多種途徑輸出模型數據:web

輸出途徑 功能說明
ModelAndView 將處理方法返回類型設爲ModelAndView。裏面封裝了咱們的模型數據,同一時候指明瞭視圖導向。

@modelAttribute 方法入參標註改註解後,入參的對象就會放到數據模型中。

Map及Model 入參爲org.springframework.ui.Model或org.springframework.ui.ModelMap或java.util.Map時,方法返回時會將Map中的數據本身主動加入到模型中
@SessionAttributes 將模型中的某個屬性暫存到HttpSession中,以便多個請求之間完畢屬性共享

如下咱們主要介紹ModelAndView
ModelAndView(如下簡稱MAV)就像它的名字同樣。既包括了模型數據又包括視圖信息。咱們返回一個MAV。springMVC就會將模型數據轉發給相應的視圖界面。
在學習ModelAndView的用法前。咱們先用肢解的方法學習其兩個重要組成部分ajax

1. model

model是一個接口,咱們可以簡單地將model的實現類理解成一個Map,將模型數據以鍵值對的形式返回給視圖層使用。在springMVC中,每個方法被前端請求觸發調用前,都會建立一個隱含的模型對象,做爲模型數據的存儲容器。spring

這是一個Request級別的模型數據。咱們可以在前端頁面如jsp中經過HttpServletRequest等相關API讀取到這些模型數據。
在model中。定義有例如如下常常使用接口方法:json

/** * 加入鍵值屬性對 */
    Model addAttribute(String attributeName, Object attributeValue);

    /** * 以屬性的類型爲鍵加入屬 */
    Model addAttribute(Object attributeValue);

    /** * 以屬性和集合的類型構造鍵名加入集合屬性,假設有同類型會存在覆蓋現象 */
    Model addAllAttributes(Collection<?> attributeValues);

    /** * 將attributes中的內容拷貝到當前的model中 * 假設當前model存在一樣內容。會被覆蓋 */
    Model addAllAttributes(Map<String, ?> attributes);

    /** * 將attributes中的內容拷貝到當前的model中 * 假設當前model存在一樣內容,不會被覆蓋 */
    Model mergeAttributes(Map<String, ?> attributes);

    /** * 推斷是否有相應的屬性值 */
    boolean containsAttribute(String attributeName);

    /** * 將當前的model轉換成Map */
    Map<String, Object> asMap();

假設咱們加入的屬性沒有指定鍵名。咱們稱之爲匿名數據綁定,它們遵循例如如下規則:
1. 對於普通數據類型,咱們直接以類型(第一字母小寫)做爲鍵值
2. 對於集合類型(Collection接口的實現者們,包括數組),生成的模型對象屬性名爲「簡單類名(首字母小寫)」+「List」,如List生成的模型對象屬性名爲「stringList」,List生成的模型對象屬性名爲「userModelList」。
後端

在ModelAndView中,咱們不少其它的是直接操做modelMap和Map來完畢咱們的模型參數準備就能夠。modelMap繼承自java.util.LinkedHashMap。數組

它在LinkedHashMap的基礎上,新增了很是多便利的構造方法如:markdown

public ModelMap(String attributeName, Object attributeValue) { addAttribute(attributeName, attributeValue); } public ModelMap addAllAttributes(Map<String, ?

> attributes) { if (attributes != null) { putAll(attributes); } return this; }

使用這些構造方法能進一步簡化咱們的模型數據封裝。

2. view

view也是一個接口,它表示一個響應給用戶的視圖如jsp文件,pdf文件,html文件。


它有兩個接口方法:
1. String getContentType():返回視圖的內容類型
2. void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception:依據給定模型和web資源定義視圖的渲染形式。


view接口有衆多的實現類,例如如下圖所看到的:
這裏寫圖片描寫敘述
在spring中。經過ViewResolver來解析相應View實例的行爲。 它的定義至關簡單:

public interface ViewResolver {
    //經過view name 解析View
    View resolveViewName(String viewName, Locale locale) throws Exception;
}

spring爲咱們提供ViewResolver實現類用來解析不一樣的view:
這裏寫圖片描寫敘述
在咱們最開始配置springMVC核心文件時,就用到了InternalResourceViewResolver,它是一個內部資源視圖解析器。

會把返回的視圖名稱都解析爲 InternalResourceView 對象。 InternalResourceView 會把 Controller 處理器方法返回的模型屬性都存放到相應的 request 屬性中。而後經過 RequestDispatcher 在server端把請求 forword 重定向到目標 URL。

如下咱們來看配置實例:

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/"></property><!-- 前綴,在springMVC控制層處理好的請求後,轉發配置文件夾下的視圖文件 -->
    <property name="suffix" value=".jsp"></property><!-- 文件後綴,表示轉發到的視圖文件後綴爲.jsp -->
</bean>

解析完Model and(和) View後,再來看咱們的ModelAndView:

public class ModelAndView { //視圖成員 private Object view; //模型成員 private ModelMap model; //是否調用clear()方法清空視圖和模型 private boolean cleared = false; /** * 空構造方法 */ public ModelAndView() { } /** * 簡便地使用視圖名生成視圖,詳細解析由DispatcherServlet的視圖解析器進行 */ public ModelAndView(String viewName) { this.view = viewName; } /** * 指定一個視圖對象生成視圖 */ public ModelAndView(View view) { this.view = view; } /** * 指定視圖名同一時候綁定模型數據。這裏模型數據以追加的形式加入在原來的視圖數據中 */ public ModelAndView(String viewName, Map<String, ?

> model) { this.view = viewName; if (model != null) { getModelMap().addAllAttributes(model); } } /** * 指定一個視圖對象同一時候綁定模型數據。這裏模型數據以追加的形式加入在原來的視圖數據中 */ public ModelAndView(View view, Map<String, ?> model) { this.view = view; if (model != null) { getModelMap().addAllAttributes(model); } } /** * 簡便配置:指定視圖名,同一時候加入單個屬性 */ public ModelAndView(String viewName, String modelName, Object modelObject) { this.view = viewName; addObject(modelName, modelObject); } /** * 簡便配置:指定一個視圖對象,同一時候加入單個屬性 */ public ModelAndView(View view, String modelName, Object modelObject) { this.view = view; addObject(modelName, modelObject); } /** * 設置當前視圖名 */ public void setViewName(String viewName) { this.view = viewName; } /** * 獲取視圖名。假設當前視圖屬性爲view而非名字(String)則返回null */ public String getViewName() { return (this.view instanceof String ? (String) this.view : null); } /** * 設置當前視圖對象 */ public void setView(View view) { this.view = view; } /** * 獲取視圖,假設非view實例,則返回null */ public View getView() { return (this.view instanceof View ? (View) this.view : null); } /** * 推斷當前視圖是否存在 */ public boolean hasView() { return (this.view != null); } /** * 獲取模型Map。假設爲空,則新建一個 */ public ModelMap getModelMap() { if (this.model == null) { this.model = new ModelMap(); } return this.model; } /** * 同getModelMap */ public Map<String, Object> getModel() { return getModelMap(); } /** * 加入單個鍵值對屬性 */ public ModelAndView addObject(String attributeName, Object attributeValue) { getModelMap().addAttribute(attributeName, attributeValue); return this; } /** * 以屬性類型爲鍵加入屬性 */ public ModelAndView addObject(Object attributeValue) { getModelMap().addAttribute(attributeValue); return this; } /** * 將Map中的所有屬性加入到成員屬性ModelMap中 */ public ModelAndView addAllObjects(Map<String, ?> modelMap) { getModelMap().addAllAttributes(modelMap); return this; } /** * 清空視圖模型。並設爲清空狀態 */ public void clear() { this.view = null; this.model = null; this.cleared = true; } /** * 推斷是否爲不含視圖和模型 */ public boolean isEmpty() { return (this.view == null && CollectionUtils.isEmpty(this.model)); } }
相關文章
相關標籤/搜索