一、Spring?MVC?提供了以下幾種途徑輸出模型數(shù)據(jù):
ModelAndView: 處理方法返回值類型為ModelAndView時(shí), 方法體即可通過該對(duì)象添加模型數(shù)據(jù)
Map?及Model: 入?yún)閛rg.springframework.ui.Model、org.springframework.ui.ModelMap 或java.uti.Map 時(shí),處理方法返回時(shí),Map中的數(shù)據(jù)會(huì)自動(dòng)添加到模型中。
@SessionAttributes: 將模型中的某個(gè)屬性暫存到HttpSession 中,以便多個(gè)請(qǐng)求之間可以共享這個(gè)屬性
@ModelAttribute: 方法入?yún)?biāo)注該注解后, 入?yún)⒌膶?duì)象就會(huì)放到數(shù)據(jù)模型中
二、ModelAndView
控制器處理方法的返回值如果為ModelAndView, 則其既包含視圖信息,也包含模型數(shù)據(jù)信息。
添加模型數(shù)據(jù):
MoelAndView addObject(String attributeName,?Object attributeValue)
ModelAndView addAllObject(Map?modelMap)
設(shè)置視圖:
void setView(View?view)
void setViewName(String?viewName)


三、Map及Model
Spring MVC?在內(nèi)部使用了一個(gè)org.springframework.ui.Model 接口存儲(chǔ)模型數(shù)據(jù)
具體步驟
Spring MVC?在調(diào)用方法前會(huì)創(chuàng)建一個(gè)隱含的模型對(duì)象作為模型數(shù)據(jù)的存儲(chǔ)容器。
如果方法的入?yún)?b>Map?或Model?類型,Spring MVC 會(huì)將隱含模型的引用傳遞給這些入?yún)?。在方法體內(nèi),開發(fā)者可以通過這個(gè)入?yún)?duì)象訪問到模型中的所有數(shù)據(jù),也可以向模型中添加新的屬性數(shù)據(jù)



四、@SessionAttributes
若希望在多個(gè)請(qǐng)求之間共用某個(gè)模型屬性數(shù)據(jù),則可以在控制器類上標(biāo)注一@SessionAttributes, Spring?MVC 將在模型中對(duì)應(yīng)的屬性暫存到HttpSession?中。
@SessionAttributes?除了可以通過屬性名指定需要放到會(huì)話中的屬性外,還可以通過模型屬性的對(duì)象類型指定哪些模型屬性需要放到會(huì)話中
@SessionAttributes(types=User.class) 會(huì)將隱含模型中所有類型為User.class 的屬性添加到會(huì)話中。
@SessionAttributes(value={“user1”,?“user2”})
@SessionAttributes(types={User.class,?Dept.class})
@SessionAttributes(value={“user1”,?“user2”}, types={Dept.class})



在類上面加上注解


五、@ModelAttribute
(1)在方法定義上使用@ModelAttribute?注解:Spring MVC在調(diào)用目標(biāo)處理方法前,會(huì)先逐個(gè)調(diào)用在方法級(jí)上標(biāo)注了@ModelAttribute 的方法。
(2)在方法的入?yún)⑶笆褂?b>@ModelAttribute?注解:
– 可以從隱含對(duì)象中獲取隱含的模型數(shù)據(jù)中獲取對(duì)象,再將請(qǐng)求參數(shù)
綁定到對(duì)象中,再傳入入?yún)?/p>
– 將方法入?yún)?duì)象添加到模型中
(3)模擬修改操作
1、原始數(shù)據(jù)放在表單的value
2、密碼不能修改
3、表單回顯,模擬操作直接在表單填寫對(duì)應(yīng)的屬性值



運(yùn)行流程:
1、執(zhí)行@ModelAttribute注解修飾的方法:從數(shù)據(jù)庫中取出對(duì)象,把對(duì)象放入到了Map中,鍵為user
2、SpringMVC從Map中取出User對(duì)象,并把表單的請(qǐng)求參數(shù)賦給改User對(duì)象的對(duì)應(yīng)屬性
3、SpringMVC把上述對(duì)象傳入目標(biāo)方法的參數(shù)
在ModelAttribute修飾的方法中,放入到Map時(shí)的鍵需要和目標(biāo)方法入?yún)㈩愋偷牡谝粋€(gè)字母小寫的字符串一致!
源代碼分析的流程
1. 調(diào)用 @ModelAttribute 注解修飾的方法. 實(shí)際上把 @ModelAttribute 方法中 Map 中的數(shù)據(jù)放在了 implicitModel 中.
2. 解析請(qǐng)求處理器的目標(biāo)參數(shù), 實(shí)際上該目標(biāo)參數(shù)來自于 WebDataBinder 對(duì)象的 target 屬性
1). 創(chuàng)建 WebDataBinder 對(duì)象:
①. 確定 objectName 屬性: 若傳入的 attrName 屬性值為 "", 則 objectName 為類名第一個(gè)字母小寫.
注意: attrName. 若目標(biāo)方法的 POJO 屬性使用了 @ModelAttribute 來修飾, 則 attrName 值即為 @ModelAttribute的 value 屬性值
②. 確定 target 屬性:
> 在 implicitModel 中查找 attrName 對(duì)應(yīng)的屬性值. 若存在, ok
?> *若不存在: 則驗(yàn)證當(dāng)前 Handler 是否使用了 @SessionAttributes 進(jìn)行修飾, 若使用了, 則嘗試從 Session 中獲取 attrName 所對(duì)應(yīng)的屬性值. 若 session 中沒有對(duì)應(yīng)的屬性值, 則拋出了異常.
> 若 Handler 沒有使用 @SessionAttributes 進(jìn)行修飾, 或 @SessionAttributes 中沒有使用 value 值指定的 key和 attrName 相匹配, 則通過反射創(chuàng)建了 POJO 對(duì)象
2). SpringMVC 把表單的請(qǐng)求參數(shù)賦給了 WebDataBinder 的 target 對(duì)應(yīng)的屬性.
3). *SpringMVC 會(huì)把 WebDataBinder 的 attrName 和 target 給到 implicitModel,進(jìn)而傳到 request 域?qū)ο笾?
4). 把 WebDataBinder 的 target 作為參數(shù)傳遞給目標(biāo)方法的入?yún)?
SpringMVC 確定目標(biāo)方法 POJO 類型入?yún)⒌倪^程
* 1. 確定一個(gè) key:
* 1). 若目標(biāo)方法的 POJO 類型的參數(shù)木有使用 @ModelAttribute 作為修飾, 則 key 為 POJO 類名第一個(gè)字母的小寫
* 2). 若使用了? @ModelAttribute 來修飾, 則 key 為 @ModelAttribute 注解的 value 屬性值.
* 2. 在 implicitModel 中查找 key 對(duì)應(yīng)的對(duì)象, 若存在, 則作為入?yún)魅?/p>
* 1). 若在 @ModelAttribute 標(biāo)記的方法中在 Map 中保存過, 且 key 和 1 確定的 key 一致, 則會(huì)獲取到.
* 3. 若 implicitModel 中不存在 key 對(duì)應(yīng)的對(duì)象, 則檢查當(dāng)前的 Handler 是否使用 @SessionAttributes 注解修飾,
* 若使用了該注解, 且 @SessionAttributes 注解的 value 屬性值中包含了 key, 則會(huì)從 HttpSession 中來獲取 key 所
* 對(duì)應(yīng)的 value 值, 若存在則直接傳入到目標(biāo)方法的入?yún)⒅? 若不存在則將拋出異常.
* 4. 若 Handler 沒有標(biāo)識(shí) @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 則
* 會(huì)通過反射來創(chuàng)建 POJO 類型的參數(shù), 傳入為目標(biāo)方法的參數(shù)
* 5. SpringMVC 會(huì)把 key 和 POJO 類型的對(duì)象保存到 implicitModel 中, 進(jìn)而會(huì)保存到 request 中.

1. 有 @ModelAttribute 標(biāo)記的方法, 會(huì)在每個(gè)目標(biāo)方法執(zhí)行之前被 SpringMVC 調(diào)用!
2. @ModelAttribute 注解也可以來修飾目標(biāo)方法 POJO 類型的入?yún)? 其 value 屬性值有如下的作用:
* 1). SpringMVC 會(huì)使用 value 屬性值在 implicitModel 中查找對(duì)應(yīng)的對(duì)象, 若存在則會(huì)直接傳入到目標(biāo)方法的入?yún)⒅?
* 2). SpringMVC 會(huì)一 value 為 key, POJO 類型的對(duì)象為 value, 存入到 request 中.
六、由@SessionAttributes引發(fā)的異常
如果在處理類定義處標(biāo)注了@SessionAttributes(“xxx”),則嘗試從會(huì)話中獲取該屬性,并將其賦給該入?yún)ⅲ缓笤儆谜?qǐng)求消息填充該入?yún)?duì)象。如果在會(huì)話中找不到對(duì)應(yīng)的屬性,則拋出HttpSessionRequiredException?異常

如何避免@SessionAttributes引發(fā)的異常
該方法會(huì)往隱含模型中添加一個(gè)名為user的模型屬性

