1. 程式人生 > >springMVC4(7)模型視圖方法源代碼綜合分析

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

ace javadoc nes ice 全部 esp gree 接受 merge

在完整web開發中。springMVC主要充當了控制層的角色。它接受視圖層的請求。獲取視圖層請求數據,再對數據進行業務邏輯處理。然後封裝成視圖層須要的模型數據,再將數據導向到jsp等視圖界面。
在前面,[email protected],完畢了視圖層->控制層的數據交接,然後業務邏輯處理主要由Service層進行。那麽接下來非常關鍵的就是,怎樣將視圖數據導向到特定的視圖中。

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

這時,我們的視圖能夠為json視圖、xml視圖、乃至PDF視圖、Excel視圖等

springMVC為我們提供了多種途徑輸出模型數據:

輸出途徑 功能說明
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的用法前。我們先用肢解的方法學習其兩個重要組成部分

1. model

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

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

    /**
     * 加入鍵值屬性對
     */
    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的基礎上,新增了非常多便利的構造方法如:

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)); } }

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