SpringMvc的@ModelAttribute註解

來自!springmvc的ModelAttribute註解java

    SpringMVC中@ModelAttribute是一個重要的屬性,理解好它是用好自動封裝等功能的基礎。可是@ModelAttribute和@RequestMapping組合後的狀況較多,很容易讓人糊塗。今天我在博客中總結一下常見的狀況。web

1、基本做用:向Model中put對象屬性

例:一個沒有使用@ModelAttribute的Controller方法.spring

@RequestMapping("/save")  
public String save(User user) {  
    user.setUsername("U love me");  
    userService.save(user);  
    return "result";  
}

其中User包含id和username兩個私有屬性,含有公共setter和getter方法.
執行此方法時會將key爲"user"(注意:這裏即便參數名稱是user1,key同樣仍是"user"),value爲user的對象加入到model.在jsp頁面能夠經過${user.id}和${user.name}獲得值的,即上面方法和下面方法是至關的.session

@RequestMapping("/save")  
public String save(Model model,int id,String username) {  
    User user=new User();  
    //這裏是經過反射從request裏面拿值再set到user  
    user.setId(id);  
    user.setUsername(username);  
    model.addAttribute("user",user);  
      
    user.setUsername("U love me");  
    userService.save(user);  
    return "result";  
}

2、@ModelAttribute的基本用法

1.在方法上使用@ModelAttributemvc

   在方法上使用@ModelAttribute("k1"),結果是向Model中添加一個鍵值對,key是"k1",value是方法的返回值。app

@ModelAttribute("user1")  
public User addUser(User user) {  
    return new User(520,"I love U");  
}

假設此方法是寫在UserController內,那麼執行UserController內帶有@RequestMapping的方法以前,都會先執行此addUser方法.而且執行addUser過程當中會添加兩個對象到model,先將key爲"user"的對象(由addUser方法的User user引發的),再添加key爲"user1"的對象(由註解@ModelAttribute("user1")引發的).框架

2.在方法參數上使用@ModelAttribute.jsp

 在方法參數上使用@ModelAttribute("k1"),結果是向Model中添加一個鍵值對,key是"k1",value是其後的對象。ui

@RequestMapping("/save")  
public String save(@ModelAttribute("userA") User user) {  
    user.setUsername("U love me");  
    userService.save(user);  
    return "result";  
}

此方法會先從model去獲取key爲"userA"的對象,若是獲取不到會經過反射實例化一個User對象,再從request裏面拿值set到這個對象,而後把這個User對象添加到model(其中key爲"userA").
使用了@ModelAttribute能夠不在括號中指定key(框架默認指定一個key),此狀況下,用與不用@ModelAttribute沒有區別.

3.在方法和方法參數上結合使用@ModelAttribute,即上面兩步的兩個方法都添加ModelAttribute,以下:spa

@ModelAttribute("user1")  
public User addUser(User user) {  
    return new User(520,"I love U");  
}  
@RequestMapping("/save")  
public String save(@ModelAttribute User user) {  
    user.setUsername("U love me");  
    userService.save(user);  
    return "result";  
}

假設要執行保存用戶操做,根據一分析可知,先執行完會產生兩個User類型的對象(一個key是"user",另外一個key是"user1")添加到model,再執行save方法,此時會先從model去找key爲"user"的對象,能找到再從request取值set到這個User對象.最後返回到jsp頁面,model裏也只有兩個User類型對象.
再來個小小假設,將上面@ModelAttribute("user1")的user1改成user,其它不變.雖然執行了addUser方法,那麼執行到save方法內,user對象的字段值仍是來源於請求,最後返回到jsp頁面,model裏也只有一個User類型對象.


4.另類:@ModelAttribute和@RequestMapping同時使用

@Controller  
@RequestMapping("/hello/")  
public class HelloWorldContorller{  
    @ModelAttribute    
    @RequestMapping("/saveA")    
    public String save(@ModelAttribute User user) {    
        user.setUsername("U love me");    
        userService.save(user);    
        return "result";    
    }    
}

此種狀況,會添加一個key爲"user"的User對象到model,還會添加一個key爲"string",value爲"result"的對象到model,而視圖名稱則變爲了"hello/saveA"而不是"result".相信通常開發者都不會這樣用.

 

三.下面再看看結合@SessionAttributes的用法.

1.先看看這段代碼

@Controller  
@RequestMapping("user")  
@SessionAttributes("test")  
public class UserController {  
    @RequestMapping(value = "test1")  
    public String test1(Map<String, Object> model, SessionStatus sessionStatus) {  
        model.put("test","something");  
        //sessionStatus.setComplete();  
        return "user/list";  
    }  
  
    @RequestMapping(value = "test2")  
    public String test2(Map<String,?>  model) {  
        Object test = model.get("test");  
        System.out.println(test);  
        return "user/list";  
    }  
}

在類級別上使用@SessionAttributes("test"),它的做用是在controller共享 model 屬性,直到調用org.springframework.web.bind.support.SessionStatus#setComplete會清除此session值.不然長期保留.所以先調用/user/test1,再調用/user/test2.在test2方法能獲得test1方法put進去的值.當移除上面的註解,由於屬性爲test的session也被清除了,因此test2方法會獲得是null.

2.再看結合@ModelAttribute的用法.

@Controller  
@RequestMapping("user")  
@SessionAttributes("test")  
public class UserController {  
    @RequestMapping(value = "test1")  
    public String test1(HttpServletRequest request) {  
        User user = new User("xiejx618");  
        request.getSession().setAttribute("test",user);  
        return "user/list";  
    }  
    @RequestMapping(value = "test2")  
    public String test2(@ModelAttribute("test") User user,SessionStatus sessionStatus) {  
        System.out.println(user.getUsername());  
        sessionStatus.setComplete();  
        return "user/list";  
    }  
}

同樣先調用/user/test1,再調用/user/test2.在test2方法能獲得test1方法set進去的值.使用了@SessionAttributes,若是在controller的方法參數上有@ModelAttribute,那麼此方法會確保屬性test的session會存在,不然會拋org.springframework.web.HttpSessionRequiredException異常,即上面代碼先不調/user/test1,直接調/user/test2就會拋此異常

我我的不多這樣用,用原始的寫法就清晰不少了,但要看明白別人寫的代碼。

相關文章
相關標籤/搜索