1. 程式人生 > >理解springMVC中的Model和Session屬性

理解springMVC中的Model和Session屬性

               

作為一個javaweb應用的開發者,你快速學習了request(HttpRequest)和Session(HttpSession)的範圍,理解這些範圍並且在這些範圍內資料和物件是如何是進出的對設計和構建web應用是非常關鍵的。

springMVC的範圍

當我用springMVC寫web應用的時候,我發現spring model和session有一點神祕—特別是與http reques、和session範圍關聯起來這些我都已經瞭解了。spring的model元素會在我的session或者request中找到嗎,如果是這樣,我怎麼控制這個過程呢,在這篇文章中我希望能夠解密springMVC的model和session是如何工作的。

spring的@MODELATTRIBUTE

這裡有好幾種向spring的Model新增資料的方式。資料或者物件通常通過在controller上的註釋方法新增到spring中的model中去。下邊這個例子中,@ModelAttribute用來將MyCommandBean的例項以key值為myRequestObject新增到model中去
@Controllerpublic class MyController @ModelAttribute("myRequestObject"public MyCommandBean addStuffToRequestScope
()
{  System.out.println("Inside of addStuffToRequestScope");  MyCommandBean bean = new MyCommandBean("Hello World",42);  return bean; } @RequestMapping("/dosomething"public String requestHandlingMethod(Model model, HttpServletRequest request) {  System.out.println("Inside of dosomething handler method"
);  System.out.println("--- Model data ---");  Map modelMap = model.asMap();  for (Object modelKey : modelMap.keySet()) {   Object modelValue = modelMap.get(modelKey);   System.out.println(modelKey + " -- " + modelValue);  }  System.out.println("=== Request data ===");  java.util.Enumeration reqEnum = request.getAttributeNames();  while (reqEnum.hasMoreElements()) {   String s = reqEnum.nextElement();   System.out.println(s);   System.out.println("==" + request.getAttribute(s));  }  return "nextpage"; }         //  ... the rest of the controller}

在一個請求的request中,任何使用@ModelAttribute註解的方法會在controller的handler方法(像上邊例子彙總的requestHandlingMethod 方法)之前被呼叫。在這些handler方法執行前,這些方法把資料增加到java.util.map中最終新增到spring Model中去。這可以通過一個簡單的實驗證明,我建立了兩個jsp頁面:index.jsp和nextpage.jsp。index.jsp中的連結用來發送request到web應用中來觸發Mycontroller中的requestHandlingMethod()方法。requestHandlingMethod()方法返回“nextpage”作為下一個檢視邏輯上的名字,在這個例子中我們解析為nextpage.jsp。 當這個小的web站點用這種方式執行的時候,controller裡邊的System.out.println方法表明了@ModelAttribute方法是如何在handler方法之前執行的。它同樣也展示了這個MyCommandBean被建立和新增到springModel中去的過程。
Inside of addStuffToRequestScopeInside of dosomething handler method--- Model data ---myRequestObject -- MyCommandBean [someString=Hello World, someNumber=42]=== Request data ===org.springframework.web.servlet.DispatcherServlet.THEME_SOURCE==WebApplicationContext for namespace 'dispatcher-servlet': startup date [Sun Oct 13 21:40:56 CDT 2013]; root of context hierarchyorg.springframework.web.servlet.DispatcherServlet.THEME_RES[email protected]204af48corg.springframework.web.servlet.DispatcherServlet.CONTEXT==WebApplicationContext for namespace 'dispatcher-servlet': startup date [Sun Oct 13 21:40:56 CDT 2013]; root of context hierarchyorg.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping==dosomething.requestorg.springframework.web.servlet.HandlerMapping.bestMatchingPattern==/dosomething.*org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER==[email protected]18fd23e4
現在的問題是“springModel資料儲存在哪?”它儲存在標準的java request範圍中嗎?答案是“是的”,從上邊的輸出可以看出,當handler方法執行的時候MyCommandBean是在model中,但是沒有在request物件中。確實,spring不會把model資料作為request的屬性,直到執行handler方法之後和下一個檢視之前(在這個例子中是nextpage.jsp)
這也可以通過列印儲存在index.jsp和nextpage.jsp中的HttpServletRequest中的資料展示出來,這兩個頁面我都使用jsp來展示HttpServletRequest的屬性
<hr /><h3>Request Scope (key==values)</h3><% java.util.Enumeration<String> reqEnum = request.getAttributeNames(); while (reqEnum.hasMoreElements()) {  String s = reqEnum.nextElement();  out.print(s);  out.println("==" + request.getAttribute(s));%><br /><% }%>

當應用開啟並且index.jsp展現的時候,你可以看到在Request範圍內沒有屬性 do something Request Scope(key==values) 在這個例子中,當“do something”連線被點選的時候觸發了MyController的handler方法執行,繼而導致nextpage.jsp被執行,考慮到這是同樣的jsp內容,再次提出不免有些囉嗦。當nextpage.jsp提出的時候,表明model的MyCommandBean在controller裡被建立,並已經被加到HttpServletRequest範圍中去了。這個spring model的屬性key已經被複制,並且當做Request屬性的key。 所以spring model資料的建立要早於handler方法的執行,在下一個檢視載入前就已經被複制到HttpServletRequest中去了。

spring Model和Request後邊的原因

你可能會疑惑為什麼spring使用model屬性,為什麼不直接將資料加到Request物件中去呢,在Rod Johnson的書中我找到了這個問題的答案。下邊就是來自這本書的關於model元素的文字。 直接給HttpServletRequest(或者Request屬性)增加元素看起來實現了相同的目的,做這件事的原因很明確,當我們檢視我們為MVC框架設定的要求的時候,應該儘可能使檢視無關的,意味著檢視技術不和HttpServletRequest繫結。

Spring的@SESSIONATTRIBUTE

現在你知道spring的model資料是如何管理的並且是如何和Httprequset屬性關聯的,那麼spring的session資料呢? spring的@SessionAttributes在controller上使用指定model屬性應該儲存在Session中。實際上,精確的講spring開發文件已經表明了@SessionAttributes註解“列出了應該儲存在Session中或者對話儲存中model屬性的名字”。 實際上,@SessionAttribute允許你做的是在載入檢視之前,告訴spring你的哪一個model Attributes將會被複制到httpSession中去。
<h3>Session Scope (key==values)</h3><%  java.util.Enumeration<String> sessEnum = request.getSession() .getAttributeNames();  while (sessEnum.hasMoreElements()) { String s = sessEnum.nextElement(); out.print(s); out.println("==" + request.getSession().getAttribute(s));%><br /><%  }%>

我在MyController中用@SessionAttributes做註解,來把同樣的model屬性加到spring Session中去。
@Controller@SessionAttributes("myRequestObject")public class MyController {  ...}

我同樣也在handler方法中增加了程式碼來展示什麼屬性在httpSession中
@SuppressWarnings("rawtypes")@RequestMapping("/dosomething")public String requestHandlingMethod(Model model, HttpServletRequest request, HttpSession session) {  System.out.println("Inside of dosomething handler method");   System.out.println("--- Model data ---");  Map modelMap = model.asMap();  for (Object modelKey : modelMap.keySet()) { Object modelValue = modelMap.get(modelKey); System.out.println(modelKey + " -- " + modelValue);  }   System.out.println("=== Request data ===");  java.util.Enumeration<String> reqEnum = request.getAttributeNames();  while (reqEnum.hasMoreElements()) { String s = reqEnum.nextElement(); System.out.println(s); System.out.println("==" + request.getAttribute(s));  }   System.out.println("*** Session data ***");  Enumeration<String> e = session.getAttributeNames();  while (e.hasMoreElements()){ String s = e.nextElement(); System.out.println(s); System.out.println("**" + session.getAttribute(s));  }   return "nextpage";}

現在,當我們使用@SessionAttributes註解後我們可以看到什麼在session物件中,包括springMVC處理一個http 請求的前中後的過程裡。結果如下,首先是index.jsp展示,我們可以看到在HttpServletRequest和httpSession中都沒有屬性資料。 do something Request Scope(key == values) Session Scope(key == values) 在handler方法執行過程中(HttpServletRequest),你可以看到MyCommandBean被加入到spring model屬性中去,但是沒有在HttpServletRequest和HttpSession範圍中。 但是在handler方法執行之後並且nextpage.jsp被載入,你可以看到model的屬性資料確實被作為屬性複製到HttpServletRequest和httpSession中。

控制對話屬性

現在你已經對spring model和Session屬性資料是如何載入到HttpServletReq。uest和httpSession有很好的理解了。但你依舊對管理spring Session中的資料心生疑惑。spring提供了移除spring Session屬性的方式,也可以在HttpSession中移除。 原文連結:http://www.intertech.com/Blog/understanding-spring-mvc-model-and-session-attributes/            

再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!希望你也加入到我們人工智慧的隊伍中來!http://www.captainbed.net

這裡寫圖片描述