在Spring MVC裡,@ModelAttribute通常使用在Controller方法的參數注解中,用于解釋model entity;但同時,也可以放在方法注解裡。
如果把@ModelAttribute放在方法的注解上時,代表的是:該Controller的所有方法在調用前,先執行此@ModelAttribute方法。下面介紹@ModelAttribute常用的三種方式。
1、@ModelAttribute注釋一個方法的參數:
1)從model中擷取資料
@Controller
public class HelloWorldController {
@ModelAttribute("user")
public User addAccount() {
return new User("jz","123");
}
@RequestMapping(value = "/helloWorld")
public String helloWorld(@ModelAttribute("user") User user) {
user.setUserName("jizhou");
return "helloWorld";
}
}
在這個例子裡,請求/helloWorld後執行helloWorld方法之前,會先執行addAccount方法。有因為,@ModelAttribute("user") User user注釋方法參數,
是以參數user的值來源于addAccount()方法中的model屬性。 此時如果方法體沒有标注@SessionAttributes("user"),那麼scope為request,如果标注了,那麼scope為session。
2)從Form表單或URL參數中擷取(實際上,不做此注釋也能拿到user對象)
@Controller
public class HelloWorldController {
@RequestMapping(value = "/helloWorld")
public String helloWorld(@ModelAttribute User user) {
return "helloWorld";
}
}
2、
@ModelAttribute注釋在方法上,當做方法攔截器使用:
如果把@ModelAttribute放在方法的注解上時,代表的是:該Controller的所有方法在調用前,先執行此@ModelAttribute方法。我們可以把這個@ModelAttribute特性,應用在BaseController當中,所有的Controller繼承BaseController,即可實作在調用Controller時,先執行@ModelAttribute方法。比如權限驗證。
@Controller
@RequestMapping(value="test")
public class PassportController {
@ModelAttribute
public void preRun() {
System.out.println("Test Pre-Run");
}
@RequestMapping(method=RequestMethod.GET)
public String index() {
return "login/index";
}
@RequestMapping(value="login", method=RequestMethod.POST)
public ModelAndView login(@ModelAttribute @Valid Account account, BindingResult result)
:
:
}
}
在調用所有方法之前,都會先執行preRun()方法。
3、@ModelAttribute放在方法上,做為Model輸出到View時使用:
1)@ModelAttribute注釋void傳回值的方法
@Controller
public class HelloModelController {
@ModelAttribute
public void populateModel(@RequestParam String abc, Model model) {
model.addAttribute("attributeName", abc);
}
@RequestMapping(value = "/helloWorld")
public String helloWorld() {
return "helloWorld.jsp";
}
}
在這個代碼中,通路控制器方法helloWorld時,會首先調用populateModel方法,将頁面參數abc(/helloWorld.ht?abc=text)放到model的attributeName屬性中,在視圖中可以直接通路。
jsp中使用:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
</head>
<body>
<c:out value="${attributeName}"></c:out>
</body>
</html>
2)@ModelAttribute注釋傳回具體類的方法
@Controller
public class Hello2ModelController {
@ModelAttribute
public User populateModel() {
User user=new User();
user.setAccount("ray");
return user;
}
@RequestMapping(value = "/helloWorld2")
public String helloWorld() {
return "helloWorld.jsp";
}
}
當使用者請求 http://localhost:8080/test/helloWorld2時,首先通路populateModel方法,傳回User對象
,model屬性的名稱沒有指定,它由傳回類型隐含表示,如這個方法傳回User類型,那麼這個model屬性的名稱是user。
這個例子中model屬性名稱有傳回對象類型隐含表示,model屬性對象就是方法的傳回值。它無須要特定的參數。
jsp中通路:
<c:out value="${user.account}"></c:out>
3)也可以指定屬性名字:
@Controller
public class Hello2ModelController {
@ModelAttribute(value="myUser")
public User populateModel() {
User user=new User();
user.setAccount("ray");
return user;
}
@RequestMapping(value = "/helloWorld2")
public String helloWorld(Model map) {
return "helloWorld.jsp";
}
}
jsp中使用:
<c:out value="${myUser.account}"></c:out>
4)合并對象:
@Controller
public class Hello2ModelController {
@ModelAttribute
public User populateModel() {
User user=new User();
user.setAccount("ray");
return user;
}
@RequestMapping(value = "/helloWorld2")
public String helloWorld(User user) {
user.setName("老王");
return "helloWorld.jsp";
}
}
合并對象也可以指定名字:
@Controller
public class Hello2ModelController {
@ModelAttribute("myUser")
public User populateModel() {
User user=new User();
user.setAccount("ray");
return user;
}
@RequestMapping(value = "/helloWorld2")
public String helloWorld(@ModelAttribute("myUser") User user) {
user.setName("老王");
return "helloWorld.jsp";
}
}
在jsp中通路:
<c:out value="${myUser.name}"></c:out>
<c:out value="${myUser.account}"></c:out>