從控制器獲取數據后,會裝載數據到數據模型和視圖中,然后將視圖名稱轉發到視圖解析器中,通過解析器解析后得到最終視圖,最后將數據模型渲染到視圖中,展示最終的結果給用戶。
用ModelAndView來定義視圖類型,包括JSON視圖,也用它來加載數據模型。ModelAndView有一個類型為ModelMap的屬性model,而ModelMap繼承了LinkedHashMap<String, Object>,因此它可以存放各種鍵值對,為了進一步定義數據模型功能,Spring還創建了類ExtendedModelMap,這個類實現了數據模型定義的Model接口,並且還在此基礎上派生了關於數據綁定的類——BindAwareModelMap,它們的關系如圖15-12所示。
用ModelAndView來定義視圖類型,包括JSON視圖,也用它來加載數據模型。ModelAndView有一個類型為ModelMap的屬性model,而ModelMap繼承了LinkedHashMap<String, Object>,因此它可以存放各種鍵值對,為了進一步定義數據模型功能,Spring還創建了類ExtendedModelMap,這個類實現了數據模型定義的Model接口,並且還在此基礎上派生了關於數據綁定的類——BindAwareModelMap,它們的關系如圖15-12所示。


在控制器的方法中,可以把ModelAndView、Model、ModelMap作為參數。在Spring MVC運行的時候,會自動初始化它們,因此可以選擇ModelMap或者Model作為數據模型。事實上Spring MVC創建的是一個BindingAwareModelMap實例,根據圖15-12的關系,可以通過強制轉換把Model變為ModelMap,或者把ModelMap轉換為Model。ModelAndView初始化后,Model屬性為空,當調用它增加數據模型的方法后,會自動創建一個ModelMap實例,用以保存數據模型,至此數據模型之間的關系介紹清楚了,讓我們用於實踐。
代碼清單15-41:測試數據模型
@RequestMapping(value = "/getRoleByModelMap", method = RequestMethod.GET) public ModelAndView getRoleByModelMap(@RequestParam("id") Long id, ModelMap modelMap) { // Role role = roleService.getRole(id); Role role = new Role(id, "射手", "遠程物理輸出"); ModelAndView mv = new ModelAndView(); mv.setViewName("roleDetails"); modelMap.addAttribute("role", role); return mv; } @RequestMapping(value = "/getRoleByModel", method = RequestMethod.GET) public ModelAndView getRoleByModel(@RequestParam("id") Long id, Model model) { // Role role = roleService.getRole(id); Role role = new Role(id, "射手", "遠程物理輸出"); ModelAndView mv = new ModelAndView(); mv.setViewName("roleDetails"); model.addAttribute("role", role); return mv; } @RequestMapping(value = "/getRoleByMv", method = RequestMethod.GET) public ModelAndView getRoleByMv(@RequestParam("id") Long id, ModelAndView mv) { // Role role = roleService.getRole(id); Role role = new Role(id, "射手", "遠程物理輸出"); mv.setViewName("roleDetails"); mv.addObject("role", role); return mv; }
在筆者的測試中,無論使用Model還是ModelMap,它都是BindingAwareModelMap實例,而BindingAwareModelMap是一個繼承了ModelMap,實現了Model接口的類,所以就有了相互轉換的功能。而getRoleByModel和getRoleByModelMap都沒有把數據模型綁定給視圖和模型,這一步是Spring MVC在完成控制器邏輯后,自動綁定的,並不需要我們綁定,也就沒有綁定的代碼了。
視圖
視圖是展示給用戶的內容,而在此之前,要通過控制器得到對應的數據模型,如果是非邏輯視圖,則不會經過視圖解析器定位視圖,而是直接將數據模型渲染便結束了;而邏輯視圖則要對其進一步解析,以定位真實視圖,這就是視圖解析器的作用了。而視圖則是把從控制器查詢回來的數據模型進行渲染,以顯示給請求者查看。
在Spring MVC中實現視圖的類很多,比如JSTL視圖JstlView,JSON視圖MappingJackson2JsonView,PDF視圖AbstractPdfView等,通過它們的render方法,Spring MVC就可以將數據模型渲染成為各類視圖,以滿足各種需求。圖15-13就是常用的視圖類和它們之間的關系,通過這些Spring MVC就能夠支持多種視圖渲染了。
在Spring MVC中實現視圖的類很多,比如JSTL視圖JstlView,JSON視圖MappingJackson2JsonView,PDF視圖AbstractPdfView等,通過它們的render方法,Spring MVC就可以將數據模型渲染成為各類視圖,以滿足各種需求。圖15-13就是常用的視圖類和它們之間的關系,通過這些Spring MVC就能夠支持多種視圖渲染了。


視圖又分為邏輯視圖和非邏輯視圖,比如MappingJack-son2JsonView是一個非邏輯視圖,它的目的就是將數據模型轉換為一個JSON視圖,展現給用戶,無須對視圖名字再進行下一步的解析
InternalResourceView是一個邏輯視圖,對於邏輯視圖而言它需要一個視圖解析器