你一定知道Model類,在控制器中,數據會存放到Model對象中,當需要生成HTML的時候,模板引擎會根據名字來定位數據,向下圖這樣。

從廣義上來說,Model指的是MVC中的M,即Model(模型)。從狹義上講,Model就是個key-value集合。實際上,上圖home方法得到的model對象就是一個 java.util.Map ,你可以將Model類型替換為Map<String, Object> ,或者ModelMap——一個實現了Model介面的java.util.HashMap

往Model裏放數據還有另外一種方式,使用ModelAndView。正如它的名字一樣,ModelAndView將Model和視圖名綁定在一起,作為請求處理方法的返回值。

有的人會傾向於這種寫法。因為請求處理方法(上圖的home方法)的參數,通常是帶有「輸入(input)」的含義的,比如我們之前介紹的@RequestParam和@PathVariable,比如我們沒有介紹過的@RequestHeader和@CookieValue,他們都是一個請求的「輸入」,通常不會變。如果將Model類作為請求處理方法的參數,並且去改變他,可能有點不太「合適」。

寫法怎麼來確定,每個人不同,只要你的選擇在項目裏始終如一就行。對於我來說,我選擇將Model作為請求處理方法的參數,不僅是因為這種寫法更新一點,簡便一點,更因為它可以獲取更多信息。我們知道Model是伴隨一個請求的整個過程的,在請求處理方法執行之前,Model有可能已經有數據了,把Model作為參數,就可以看到方法執行之前的數據了。接下來,我們看看,在方法執行之前如何給Model裏添加數據。

@ModelAttribute的用法

在所有的請求處理方法執行之前,你有機會往Model裡面加數據:新建一個方法,加上@ModelAttribute註解和Model參數,就可以像下圖這種樣加數據了。

注意,每個請求處理方法在執行之前,都會執行一次fillData方法。雖然fillData不是@RequestMapping方法,不能指定請求路徑,但是可以添加很多請求處理方法的參數,比如@RequestParam,@RequestHeader等。比如你的HTTP請求裏有一個Header是自定義的,那麼你可以在fillData方法裏,獲取到Header的信息,再根據它獲取一些數據比如用戶信息什麼的,放到Model裏。

如果fillData裏的數據很少,只有一個對象,你可以直接把這個對象返回,它會自動被加入到Model裏,相當於隱性執行了Model的addAttribute(Object)方法。下圖中你可以看到,雖然你沒有指明在Model中User對象的名字,但是Model自動給它了一個名字「user」,因為你不提供名字(即key)的話,框架會根據類名生成一個,規則是類名首字母小寫(User->user)。這個key如果你想改,就給fillData方法的@ModelAttribute註解添加一個參數。

@ModelAttribute還有一種用途是作為請求處理方法的參數,如果你需要Model中某個對象,可以給參數添加@ModelAttribute註解:

如果Model中沒有User對象,那麼框架會創建一個,並放到Model中,也就是說user變數肯定不為空。然後呢,GET請求或者POST請求的參數,會跟user對象的成員(fields)名稱進行對應,對的上的話就賦值給成員。這個過程也叫做數據綁定(Data Binding),一個典型的應用就是處理表單。因為這種用法太常見了,所以@ModelAttribute也是可以省略的,請求處理方法的參數,如果不是框架能識別的類型,都會假定它用了@ModelAttribute。

文本不打算對數據綁定這一塊兒進行說明,因為東西還挺多的,之後介紹表單處理的時候我們再詳細解讀。

博客鏈接:fookwood.com/spring-boo


推薦閱讀:
相關文章