Spring MVC:Model、View、ModelAndView


個人理解:View為服務器上的某個文件容器,可以為JSP,FTL等動態頁面文件,甚至是媒體文件等等,單單是一個文件。Model的作用是存儲動態頁面屬性,動態頁面文件即View可以在Model中獲取動態數據,這樣就實現了View和Model分離的目的。接下來分別對這三個做一下說明。

一、首先是View:View接口在org.springframework.web.servlet.View包內。核心方法:

  1、getContentType()獲取當前view的ContentType(),同http請求中的ContenType()是一樣的作用。

  2、render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)。

  render(使成為;遞交;給予;表達;渲染)Dispatcher(發報機; 收發; 調度;調度員 )

  根據參數就可以知道,這個是為視圖綁定Request,Response和Model的方法。

  3、View的一個實現類AbstractView,其中有方法:

(s&g)BeanName(String beanName)

  (s&g)ContentType(String contentType)

  (s&g)RequestContextAttribute(String requestContextAttribute)

  setAttributesCSV(String propString)

  setAttributes(java.util.Properties attributes)

  (s&g)AttributesMap(Map<String, ?> attributes) 

  addStaticAttribute(String name, Object value)

  Map<String, Object> getStaticAttributes()

  (s&i)ExposePathVariables(boolean exposePathVariables)

  Map<String, Object> createMergedOutputModel(Map<String, ?> model, HttpServletRequest request,HttpServletResponse response)

  RequestContext createRequestContext(HttpServletRequest request, HttpServletResponse response, Map<String, Object> model)

  renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response)

  exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request)

  writeToResponse(HttpServletResponse response, ByteArrayOutputStream baos)
  setResponseContentType(HttpServletRequest request, HttpServletResponse response)

  其中后面的是與組合Model和Response的方法。

  根據源碼可知,View其中的staticAttributes其實最終還是給了Model,通過mergedModel.putAll(pathVars);

  4、view的子接口SmartView,唯一一個方法isRedirectView,用於標記是否是重定向View。

  RedirectView實現SmartView接口,繼承AbstractUrlBasedView,AbstractUrlBasedView又繼承自AbstractView,就是一個基本的Url的View,內部方法:

  包含一個url屬性,標記重定向到哪個url,還有一系列和http相關的協議參數,如encodingScheme,statusCode,contextRelative等等,以及其他實現View中的方法。

 二、model,model相對簡單,就是一些屬性的鍵值對而已。merge(融合,整合)

  1、方法有:

  Model addAttribute(String attributeName, Object attributeValue);  

  Model addAttribute(Object attributeValue);

  Model addAllAttributes(Collection<?> attributeValues);

  Model addAllAttributes(Map<String, ?> attributes);

  Model mergeAttributes(Map<String, ?> attributes);

  boolean containsAttribute(String attributeName);

  Map<String, Object> asMap();

  其中只加值的時候,屬性名通過org.springframework.core.Conventions的getVariableName生成。

  該接口的實現類為ExtendedModelMap,特殊的,ExtendedModelMap繼承了ModelMap類,而ModelMap其實是繼承了LinkedHashMap<String, Object>類。

  ExtendedModelMap的所有方法,都在ModelMap中實現了。

  2、Model有個子接口RedirectAttributes,用於設置重定向的屬性。比Model里面多了一個Model,RedirectAttributes中其實是有兩個Map的。

  RedirectAttributes addFlashAttribute(String attributeName, Object attributeValue);

  RedirectAttributes addFlashAttribute(Object attributeValue);

  Map<String, ?> getFlashAttributes();

  他的實現類為RedirectAttributesModelMap,同樣繼承自ModelMap,內部成員有DataBinder數據用於數據綁定,flashAttributes則是另一個Map,保存着重定向的屬性。

  該類構造時直接傳入一個數據綁定器,可為null,RedirectAttributesModelMap(org.springframework.validation.DataBinderdataBinder)

  轉發與重定向區別可參考(http://www.cnblogs.com/shenliang123/archive/2011/10/27/2226892.html)

三、ModelAndView,顧名思義,就是整合了Model和View,常用於動態頁面也是,一個后台網頁就包含這兩部分,前台就是基本的html代碼。

  內部包含一個Object類型的view,一個ModelMap類型的model,還有一個標記是否被clear()方法清除的cleared變量。

  構造方法:ModelAndView()

  ModelAndView(String viewName)

  ModelAndView(View view)

  ModelAndView(String viewName, Map<String, ?> model)

  ModelAndView(View view, Map<String, ?> model)

  ModelAndView(String viewName, String modelName, Object modelObject)

  ModelAndView(View view, String modelName, Object modelObject)

  (s&g)ViewName

  (s&g)View

  boolean hasView

  isReference:如果view instanceof String則為true

  Map<String, Object> getModelInternal()

  ModelMap getModelMap()

  Map<String, Object> getModel() 

  ModelAndView addObject(String attributeName, Object attributeValue)

  ModelAndView addObject(Object attributeValue)

  ModelAndView addAllObjects(Map<String, ?> modelMap)

  void clear():清除其中的view和model

  由此可以看出,構造View可以直接使用字符串,相當於路徑引用View

 四、最后,這幾個實際中到底是在哪使用,如何使用的呢?

  Spring架構中,他是使用在@Controller層中的@RequestMapping注解方法中的,該注解方法有以下幾種:

  返回值可以有:ModelAndView, Model, ModelMap, Map,View, String, void

  參數可以任意多,參數可以為POJO對象,可以為PO,可以為Array,List,String等等,只要能和Request中參數名一致,Spring就會自動綁定到特定的數據類型中,非常方便。其中有三個特殊類型的參數:HttpServletRequest request, HttpServletResponse response, Model model,其中第一個為當前網頁發過來的請求,第二個是要返回的形影,第三個則是當前網頁發過來的model參數集以及要設置給返回視圖的參數集Model。

  注:參數中的Model也可以變為同樣的Map,或者ModelMap,三者等價。

  來看看不同類型的返回值代表什么吧。

  1、ModelAndView

@RequestMapping("/show1") 
public ModelAndView show1(HttpServletRequest request, 
           HttpServletResponse response) throws Exception { 
       ModelAndView mav = new ModelAndView("/demo2/show"); 
       mav.addObject("account", "account -1"); 
       return mav; 
   } 

  這種是直接把View和Model封裝好返回給Spring,Spring再交給動態網頁架構去返回靜態html給客戶端。

  通過ModelAndView構造方法可以指定返回的頁面名稱,也可以通過setViewName()方法跳轉到指定的頁面 ,使用addObject()設置需要返回的值,addObject()有幾個不同參數的方法,可以默認和指定返回對象的名字。
  2、Model=ModelMap=Map,是一樣的

@RequestMapping("/demo2/show") 
    public Map<String, String> getMap() { 
        Map<String, String> map = new HashMap<String, String>(); 
        map.put("key1", "value-1"); 
        map.put("key2", "value-2"); 
        return map; 
    } 

  相當於把Map返回給當前網頁。在jsp頁面中可直通過${key1}獲得到值, map.put()相當於request.setAttribute方法。key值包括 - . 時會有問題.

  3、View 可以返回pdf excel等各種View,此時該View的Model可以在方法傳遞的參數中設置。只需在方法中加上參數Model model,對該model設置屬性,都會反饋到該View中。

  4、String,其實也是View,該View是urlView,指定返回的視圖頁面名稱,結合設置的返回地址路徑加上頁面名稱后綴即可訪問到。

@RequestMapping(value = "/something", method = RequestMethod.GET) 
@ResponseBody 
public String helloWorld()  { 
return "Hello World"; 
} 

  注意:如果方法聲明了注解@ResponseBody ,則會直接將返回值輸出到頁面。上面的結果會將文本"Hello World "直接寫到http響應流。

  若沒有注解@ResponseBody,則對應的邏輯視圖名為“center”,URL= prefix前綴+視圖名稱 +suffix后綴組成。如果以絕對路徑書寫,則在applicationContext路徑為根的目錄下尋找View。

@RequestMapping("/welcome") 
public String welcomeHandler() { 
  return "center"; 
} 

  最后一個特殊的為void,響應的視圖頁面對應為訪問地址。

@RequestMapping("/welcome") 
public void welcomeHandler() {} 

  此例對應的邏輯視圖名為"welcome"。

  PS:1.使用 String 作為請求處理方法的返回值類型是比較通用的方法,這樣返回的邏輯視圖名不會和請求 URL 綁定,具有很大的靈活性,而模型數據又可以通過 ModelMap 控制。
  2.使用void,map,Model 時,返回對應的邏輯視圖名稱真實url為:prefix前綴+視圖名稱 +suffix后綴組成。
  3.使用String,ModelAndView返回視圖名稱可以不受請求的url綁定,ModelAndView可以設置返回的視圖名稱。

  補充:

  Model model,HttpServletRequest request, ModelMap map聲明變量,都可以賦屬性和屬性值,具體先引用誰呢?

    request.getSession().setAttribute("test", "haiwei2Session");
    request.setAttribute("test", "haiwei1request"); 
    map.addAttribute("test", "haiweiModelMap");
    model.addAttribute("test", "haiweiModel");

  通過${test}取值,優先取Model和ModelMap的,Model和ModelMap是同一個東西,誰最后賦值的就取誰的,然后是request,最后是從session中獲取。

  更多內容參考:http://www.360doc.com/content/14/0309/19/834950_359081989.shtml


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM