spring mvc(4)處理模型資料
阿新 • • 發佈:2018-11-11
處理模型資料
Spring MVC 提供了以下幾種途徑輸出模型資料: – ModelAndView: 處理方法返回值型別為 ModelAndView時, 方法體即可通過該物件新增 模型資料 – Map 及 Model: 入參為org.springframework.ui.Model、org.springframework.ui. ModelMap 或 java.uti.Map 時,處理方法返回時,Map 中的資料會自動新增到模型中。 – @SessionAttributes: 將模型中的某個屬性暫存到 HttpSession 中,以便多個請求之間可以共享這個屬性 – @ModelAttribute: 方法入參標註該註解後, 入參的物件就會放到資料模型中
注:下面的程式碼均來自上一篇的註解程式碼之後的測試程式碼!!
ModelAndView
控制器處理方法的返回值如果為 ModelAndView, 則其既 包含檢視資訊,也包含模型資料資訊。 新增模型資料: – MoelAndView addObject(String attributeName, Object attributeValue) – ModelAndView addAllObject(Map<String, ?> modelMap) 設定檢視: – void setView(View view) – void setViewName(String viewName)
TestRequestMapping.java
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
String viewName="success";
ModelAndView andView = new ModelAndView(viewName);
andView.addObject("time", new Date());
return andView;
}
index.jsp
<a href="springmvc/testModelAndView">testModelAndView</a>
success.jsp;
time:${requestScope.time}
總結:SpringMVC會把ModelAndView的model中資料放入到request域物件中
Map 及 Model
Spring MVC 在內部使用了一個org.springframework.ui.Model 介面儲存模型資料
具體步驟 – Spring MVC 在呼叫方法前會建立一個隱含的模型物件作為模型資料的儲存容器。 – 如果方法的入參為 Map 或 Model 型別,Spring MVC 會將隱含模型的引用傳 遞給這些入參。在方法體內,開發者可以通過這個入參物件訪問到模型中的所有數 據,也可以向模型中新增新的屬性資料
目標方法可以新增Map型別(實際上是Model或者ModelMap型別)的引數
TestRequestMapping.java
@RequestMapping("/testMap") public String testMap(Map<String, Object> map){ map.put("name", "MrChengs"); return "success"; }
indexjsp
<a href="springmvc/testMap">testMap</a>
success.jsp
name:${requestScope.name}
@SessionAttributes
只能放在類的上面
若希望在多個請求之間 共用某個模型屬性資料,則可以在 控制器類上標註一個 @SessionAttributes, Spring MVC 將在模型中對應的屬性暫存到 HttpSession 中。
@SessionAttributes 除了可以通過 屬性名指定需要放到會話中的屬性外 (value) 還可以通過模型屬性的 物件型別指定哪些模型屬性需要放到會話中 (type)
– @SessionAttributes( types=User.class) 會將隱含模型中所有型別 為 User.class 的屬性新增到會話中。 – @SessionAttributes( value={“user1”, “user2”}) – @SessionAttributes(types={User.class, Dept.class}) – @SessionAttributes(value={“user1”, “user2”}, types={Dept.class})
TestRequestMapping.java
@SessionAttributes(value="user") @Controller @RequestMapping("/springmvc") public class TestRequestMapping { @RequestMapping("/testSessionAttributes") public String testSessionAttributes(Map<String,Object> map){ User user = new User("MrChangs", "1234", "[email protected]"); map.put("user", user); return "success"; } }
index.jsp
<a href="springmvc/testSessionAttributes">testSessionAttributes</a>
success.jsp
user requestScope:${requestScope.user} <br> <br> user sessionScope:${sessionScope.user}
@ModelAttribute
模擬修改資料路中的資料,有些不能修改。 index.jsp<!-- 模擬修改操作 1.原始資料:id=1,name=MrChengs,pw=1234,[email protected] 2.密碼不能修改 3.表單回顯,模擬操作直接在表單填寫對應的額屬性值 --> <form action="springmvc/ModelAttribute" method="post"> <input type="hidden" name="id" value="1"> <br> name:<input type="text" name="username" value="MrChengs"> <br> email:<input type="text" name="email" value="[email protected]"> <br> <input type="submit" value="submit"> </form>
//標記的方法會在每個目標方法執行之前被呼叫 //1.由@ModelAttribute標記的方法,會把每個目標之前被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, "MrChengs", "1234", "[email protected]"); System.out.println("得到一個引數"); //注意:這裡的key為users,如果改為users等其他字元,等不到結果,程式可以正常的執行 //解決方法在下面的程式碼中 map.put("users", user); } } @RequestMapping("/ModelAttribute") public String testModelAttribute(@ModelAttribute("users")User user){ System.out.println("update:" + user); return "success"; }在success頁面: 可以使用如下的方法獲得列印值
user:${requestScope.users}
如果不新增@ModelAttribut,在測試中程式碼的值為null
執行過程: 1.執行@ModelAttribute註解修飾的方法,把資料取出防砸map中,map的key為user 2.SpringMVC從Map中取出User物件,並把表單請求引數放到賦給給該user物件多的對應屬性 3.SpringMVC把上述物件傳入目標方法的引數 注意:在MOdelAttribute修飾的方法中,放入map的鍵需要和入參第一個字母小寫的字串一致
SpringMVC確定目標方法POJO型別入參的過程: 1.確定一個key 2.在implicitModel中查詢對應的key物件,若存在,則作為入參傳入 3.在implicitModel中不存在key物件,則查詢當前的Handler,是都使用了@SessionAttribute對應的 value值若存在則直接傳入到方法的入參中,不存在拋異常 4.若Handler沒由標識的@SessionAttribute註解或者@Session Attribute的value值不包含key,則會通過 反射來建立pojo型別的引數,作為目標方法的引數 5.SpringMVC會把key和value儲存到impliciModel中,進而會儲存早request中
關於@SessionAttribute的異常 java類: 注意這裡@SessionAttribute(user)和方法中的user同名
@SessionAttributes(value="user") @Controller @RequestMapping("/springmvc") public class TestRequestMapping { @RequestMapping("/ModelAttribute") public String testModelAttribute(User user){ System.out.println("update:" + user); return "success"; } }在ModelAttribute方法的user 沒找到就去@SeeionAttribute中找 所以此時會報錯----拋異常 解決方案: 1.寫ModelAttribute註解下的方法 2.表明一個modelAttribute,在第一次查詢中賦值,不在第二次找SeesionAttribute
public String testModelAttribute(@ModelAttribute("acbc")User user){
十月 16, 2018 4:38:06 下午 org.apache.catalina.core.StandardWrapperValve invoke 嚴重: Servlet.service() for servlet [springDispatcherServlet] in context with path [/Spring_MVC_01] threw exception [Session attribute 'user' required - not found in session] with root cause org.springframework.web.HttpSessionRequiredException: Session attribute 'user' required - not found in session at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.raiseSessionRequiredException(AnnotationMethodHandlerAdapter.java:791)
@ModelAttribute
在方法定義上使用 @ModelAttribute 註解:Spring MVC 在呼叫目標處理方法前,會先逐個呼叫在方法級上標註了 @ModelAttribute 的方法。 在方法的入參前使用 @ModelAttribute 註解: – 可以從隱含物件中獲取隱含的模型資料中獲取物件,再將請求引數定到物件中,再傳入入參 – 將方法入參物件新增到模型中
由@SessionAttributes引發的異常
org.springframework.web.HttpSessionRequiredExcept: Session attribute 'user' required - not found in session
如果在處理類定義處標註了@SessionAttributes(“xxx”),則嘗試從會話中獲取該屬性,並將其賦給該入參,然後再用 請求訊息填充該入參物件。 如果在會話中找不到對應的屬 性,則丟擲 HttpSessionRequiredException 異常
如何避免@SessionAttributes引發的異常