天天看點

SpringMVC---處理模型資料

ModuleAndView

SpringMVC---處理模型資料
  • 注意:ModelAndView的類型為:org.springframework.web.servlet.ModelAndView;
  • 示例使用ModuleAndView處理模型資料
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView() {
    String viewName = SUCCESS;
    ModelAndView modelAndView = new ModelAndView(viewName);
    modelAndView.addObject("info", "你好");

    return modelAndView;
}
           
  • 使用ModuleAndView實際上會将資料使用request.setAttribute()方法儲存在請求域之中.是以可以在頁面中使用EL表達式擷取請求屬性.
  • 跳轉的頁面
<body>
	<h1>${info}</h1>
</body>
           
  • 測試通路路徑:http://localhost:8080/SpringMVCModule1/testModelAndView
  • 執行結果
SpringMVC---處理模型資料
SpringMVC---處理模型資料

Map處理模型資料

SpringMVC---處理模型資料
  • 示例:
@RequestMapping("/testMap")
    public String testMap(Map<String,Object> map){
        map.put("time",new Date());
        map.put("tom","xiemaoshu");
        return SUCCESS;
    }

           
  • SpringMVC會将資料存儲到 Request範圍域之中,在頁面中可以使用 EL表達式取出資料
<h1>${time}</h1>
<h1>${tom}</h1>
           
  • 執行效果
SpringMVC---處理模型資料

@SessionAttributes

SpringMVC---處理模型資料
  • @SessionAttribute注解使用示例
//将名稱為"user"的屬性添加到Session屬性之中,也将String類型的屬性添加到Session屬性之中
@SessionAttributes(types = {User.class,String.class},value = {"user"})
@Controller
public class HelloWorld {

    @RequestMapping("/testSessionAttribute")
    public  String testSessionAttribute(Map<String,Object> map){
        User user = new User();
        user.setUid(11);
        user.setUname("xiemaoshu");
        user.setPassword("xiemaoshu20190309xms");
        map.put("user",user);
        map.put("time",new Date());
        return SUCCESS;
    }
           
  • 顯示頁面
<h1>${user}</h1>
<h1>${time}</h1>
           
  • 效果
SpringMVC---處理模型資料

@ModuleAttribute注解

遇到的問題?

  • 如果此時要進行對資料庫中的一個資料進行修改操作,但是要求:某一個字段的内容不允許被修改.例如:修改一個使用者的資料"User",使用者資料中的建立時間與密碼資訊是不允許被修改的.如果從表單中直接收要修改的資料,那麼在操作方法中往往需要提供一個User類執行個體化對象,那麼這個User類執行個體化對象中,"建立時間"和"密碼"字段隻能夠是"null"空,如何能夠放置出現null的情況?

實作的思路有兩種:

  1. 由表單填入修改資料,但是不提供"建立時間"和"密碼"的修改操作,将使用者的建立時間和密碼資訊由隐藏域儲存起來,接着再調用方法中new一個執行個體化對象,将修改資料儲存到新的執行個體化對象之中.

    - 這樣做有一個缺點就是:重要的資訊不适合放在隐藏域中,況且,如果不能夠修改的字段比較多的話,需要設定多個隐藏域.

SpringMVC---處理模型資料
  1. 先從資料庫中讀取出要修改的使用者資訊,而後隻提供要修改的資料操作
SpringMVC---處理模型資料

使用@ModuleAttribute解決

  • 模拟一個資料修改操作
  1. 修改頁面表單
<body>

<%--
    模拟一個資料修改操作
    原始資料為:
    uid=1
    password=12345
    uname=xiemaoshu
--%>
<form method="post" action="testModelAttribute">
    <div>
        使用者id:<input type="text" name="uid" id="uid" value="1"/>
    </div>

    <div>
        使用者名稱:<input type="text" name="uname" id="uname" value="xiemaoshu"/>
    </div>
    <div>
        <input type="submit" value="送出"/>
    </div>
</form>

</body>
           
  • 進行修改操作的方法
@ModelAttribute//SpringMVC在執行映射請求方法之前,會先調用帶有@ModelAttribute 注解的方法
    public void getUser(@RequestParam(value = "uid",required = false) Integer uid,Map<String,Object> map){

        //模拟從資料庫中擷取使用者資料
        User user =new User();
        user.setUid(uid);
        user.setUname("xiemaoshu");
        user.setPassword("12345");
        map.put("user",user);//将user資料儲存到request請求域之中
        
        System.out.println("擷取uid = "+uid+" 的使用者資料"+user);
    }

    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(User user){
        System.out.println("執行修改操作:"+user);
        return SUCCESS;
    }
           
  • 測試結果
SpringMVC---處理模型資料
  • 背景輸出
  • 可以發現password不為null,這是因為在執行請求方法前,會先執行"@ModelAttribute"注解的方法
SpringMVC---處理模型資料

@ModelAttribute運作原理

  • 運作流程:
    1. 執行@ModelAttribute注解修飾的方法:從資料庫中取出資料,将資料放入到了Map中,鍵為:user
    2. SpringMVC從map中取出User對象,并把表單的請求參數付給該User對象的對應屬性,
    3. SpringMVC把上述對象傳入目标方法的參數.
  • 注意:在ModelAttribute修飾的方法中,放入到Map時的鍵需要和目标方法入參類型的第一個字母小寫的字元串一緻

@ModelAttribute注解之源碼分析

  1. 調用@ModelAttribute注解修飾的方法,實際上把@ModelAttribute方法中Map中的資料放在了implicitModel中
  2. 解析請求處理器的目标參數,實際上該目标來自于WebDataBinder對象的target屬性
  3. 建立WebDataBinder對象:
    1. 确定objectName屬性:若傳入的arrtName屬性值為空字元串,則objctName為類名第一個字母小寫.(=乳溝目标方法的POJO回資訊使用了@ModelAttribute來修飾,則attrName值即為@ModelAttribute的value屬性值==)
    2. 确定target屬性:
      • 在implicitModel中查找attriName對應的屬性值.
      • 若不存在:則驗證目前的Hiddler是否使用了@SessionAttribute進行修飾,若使用了,則嘗試從Session中擷取arrtName所對應的屬性值,若session中沒有對應的屬性值,則抛出異常.
      • 若Handler沒有使用@SessionAttribute進行修飾,或@SessionAttributes中沒有使用value值指定的key和attrName相比對,則通過反射建立了POJO對象.
  4. SpringMVC把表單中請求參數賦給WebDataBinder的target屬性.
  5. SpringMBC會把WebDataBinder的attrName和target給到implicitModel
  6. 把webDataBinder的target作為參數傳遞給目标方法的入參.
  • 在"@ModelAttribute"注解的方法中和請求的方法中打上斷點

繼續閱讀