天天看點

SpringMVC----處理模型資料[email protected](13)

[email protected] 注解:Spring MVC 在調用目标處理方法前,會先逐個調用在方法級上标注了@ModelAttribute 的方法。

                                         (注意是每個目标方法之前都會調用該方法)

2.代碼示例

   2.1 需求。

SpringMVC----處理模型資料[email protected](13)

            正常更新資料庫中的一條記錄,記錄中有的字段時不能發生改變的,比如記錄的建立時間。這樣的話,會從jsp頁面

            得到隻有以上為例,兩個字段的參數,放入一個建立的對象,此時該對象隻有兩個屬性,有一個不能修改的為空。這樣

            在執行更新操作的時候,就會覆寫資料的記錄,使得不能修改的字段的值為空。為了解決該問題,有了如下方法:

SpringMVC----處理模型資料[email protected](13)

           在得到jsp頁面的兩個參數的時候,先從資料庫把該條記錄查出來,這樣不能修改的屬性也有了資料。再把jsp頁面的

          參數指派給對應的屬性,執行更新操作。

   2.2 jsp頁面請求。

<form action="springMVC/testModelAttribute" method="Post">
	<input type="hidden" name="id" value="1"/>
	username: <input type="text" name="username" value="Tom"/>
	<br>
	email: <input type="text" name="email" value="[email protected]"/>
	<br>
	age: <input type="text" name="age" value="10"/>
	<br>
	<input type="submit" value="Submit"/>
</form>
           

2.3 目标方法。通過@ModelAttribute注解的方法,在調用目标方法之前,先調用改方法,裝配model,查出資料。指派

                        給model。

/**
*[email protected] 标記的方法,會在每個目标方法執行之前被SpringMVC調用
*[email protected]注解也可以用來修飾目标方法POJO類型的入參,其value屬性
*  值有如下的作用:
*   2.1 SpringMVC會使用value的屬性值,在implicitModel中查找對應的對象,
*        若存在則會直接傳入到目标方法的入參中。
*   2.2 SpringMVC會以value為key,POJO類型的隊對象為value,存入到request中。
*/
@ModelAttribute
public void getUser(@RequestParam(value="id",required=false) Integer id,
		Map<String,Object> map){
	if(id != null){
          User user = new User(1, "Tom", "1234586", "[email protected]", 12);
          System.out.println("database from :" + user);
          map.put("user", user);
	}

}
/**
* 運作流程:
* 1. 執行 @ModelAttribute 注解修飾的方法: 從資料庫中取出對象, 把對象放入到了 Map 中. 鍵為: user
* 2. SpringMVC 從 Map 中取出 User 對象, 并把表單的請求參數賦給該 User 對象的對應屬性.
* 3. SpringMVC 把上述對象傳入目标方法的參數. 
* 
* 注意: 在 @ModelAttribute 修飾的方法中, 放入到 Map 時的鍵需要和目标方法入參類型的第一個字母小寫的字元串一緻!
* 
* SpringMVC 确定目标方法 POJO 類型入參的過程
* 1. 确定一個 key:
* 1). 若目标方法的 POJO 類型的參數木有使用 @ModelAttribute 作為修飾, 則 key 為 POJO 類名第一個字母的小寫
* 2). 若使用了  @ModelAttribute 來修飾, 則 key 為 @ModelAttribute 注解的 value 屬性值. 
* 2. 在 implicitModel 中查找 key 對應的對象, 若存在, 則作為入參傳入
* 1). 若在 @ModelAttribute 标記的方法中在 Map 中儲存過, 且 key 和 1 确定的 key 一緻, 則會擷取到. 
* 3. 若 implicitModel 中不存在 key 對應的對象, 則檢查目前的 Handler 是否使用 @SessionAttributes 注解修飾, 
* 若使用了該注解, 且 @SessionAttributes 注解的 value 屬性值中包含了 key, 則會從 HttpSession 中來擷取 key 所
* 對應的 value 值, 若存在則直接傳入到目标方法的入參中. 若不存在則将抛出異常. 
* 4. 若 Handler 沒有辨別 @SessionAttributes 注解或 @SessionAttributes 注解的 value 值中不包含 key, 則
* 會通過反射來建立 POJO 類型的參數, 傳入為目标方法的參數
* 5. SpringMVC 會把 key 和 POJO 類型的對象儲存到 implicitModel 中, 進而會儲存到 request 中. 
* 
* 源代碼分析的流程
* 1. 調用 @ModelAttribute 注解修飾的方法. 實際上把 @ModelAttribute 方法中 Map 中的資料放在了 implicitModel 中.
* 2. 解析請求處理器的目标參數, 實際上該目标參數來自于 WebDataBinder 對象的 target 屬性
* 1). 建立 WebDataBinder 對象:
* ①. 确定 objectName 屬性: 若傳入的 attrName 屬性值為 "", 則 objectName 為類名第一個字母小寫. 
* *注意: attrName. 若目标方法的 POJO 屬性使用了 @ModelAttribute 來修飾, 則 attrName 值即為 @ModelAttribute 
* 的 value 屬性值 
* 
* ②. 确定 target 屬性:
* 	> 在 implicitModel 中查找 attrName 對應的屬性值. 若存在, ok
* 	> *若不存在: 則驗證目前 Handler 是否使用了 @SessionAttributes 進行修飾, 若使用了, 則嘗試從 Session 中
* 擷取 attrName 所對應的屬性值. 若 session 中沒有對應的屬性值, 則抛出了異常. 
* 	> 若 Handler 沒有使用 @SessionAttributes 進行修飾, 或 @SessionAttributes 中沒有使用 value 值指定的 key
* 和 attrName 相比對, 則通過反射建立了 POJO 對象
* 
* 2). SpringMVC 把表單的請求參數賦給了 WebDataBinder 的 target 對應的屬性. 
* 3). *SpringMVC 會把 WebDataBinder 的 attrName 和 target 給到 implicitModel. 
* 近而傳到 request 域對象中. 
* 4). 把 WebDataBinder 的 target 作為參數傳遞給目标方法的入參. 
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){
	System.out.println("修改:"+user);
	return SUCCESS;
}
           

2.4  解讀:我在有@ModelAttribute注解的方法中查到了一天記錄,并且把它放入到了map集合中 map.put("user", user);

                  然後我在目标方法(testModelAttribute(User user))中就直接擷取到了上面的放入map中的記錄(user),在

                  2.3裡面介紹了SpringMVC是如何擷取該記錄的。在我沒有給目标方法的POJO入參添加@ModelAttribute注解之前

                 我之是以能夠在目标方法中準确地得到的放入map中的user,是因為我在 map.put("user", user)時,map的key值

                 是下面目标方法POJO入參的類型的第一個字母的小寫,是以我可以得到。

                  那麼,一旦我在 map.put("user", user)時,key放入的值不是user,而是,abc等其他,不是目标方法POJO入參的類

                  型的第一個字母的小寫的字元串時,在沒有給目标方法的POJO入參添加@ModelAttribute注解之前,因為SpringMVC

                 找不到對應的資料,(因為我放入map的時候沒有按照規則命名),是以會根據目标方法的POJO類入參的類型依靠

                 反射去擷取一個新的模型,那麼,這個新的model是沒有從資料庫查出來的某些屬性的。

                 但是,如果在目标方法的POJO入參添加@ModelAttribute注解,就可以不用按照規則在map中放入model,但是此時

                  @ModelAttribute(“aaa”)注解的value值,必須和放入map中的model的key值一緻。(map.put("aaa", user))

                  這就是@ModelAttribute使用在目标方法POJO類型入參的作用。

                 在正常情況下,是不用在目标方法POJO類型入參出添加@ModelAttribute注解的,預設我們都會在map放入的時候

                 使用POJO類型入參的第一個字母小寫的字元串。

繼續閱讀