@ModelAttribute最主要的作用相当于model.addattribute也就是将数据添加到模型对象中,用于视图页面展示时使用或者后端请求函数中使用(@ModelAttribute标注的方法会在每个请求处理方法执行前执行)。
先看一个没有使用@ModelAttribute的Controller方法,其中User包含id和username两个私有属性,含有公共setter和getter方法;执行此方法时会将key为"user",value为user的对象加入到model。在jsp页面可以通过 u s e r . i d 和 {user.id}和 user.id和{user.name}得到值的。
@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";
}
下面开始讲解加了@ModelAttribute后又会有什么不同
模型对象主要有(Model、ModelMap和ModelAndView) 三者的区别和联系可以参考:https://blog.csdn.net/itbiggod/article/details/79685610 @ModelAttribute注解的作用相当于model.addattribute
1 用@ModelAttribute来标注方法(当 @ModelAttribute 标记在方法上的时候,该方法会在controller的每个方法执行前被执行,因此对于一个controller映射多个URL的用法来说,要谨慎使用。)
(1) @ModelAttribute(value="")标注带返回具体值的方法
这个例子中使用@ModelAttribute的value属性,来指定model属性的名称。相当于model.addattribute(“attributeName”,“abc”) ,attributeName 为key,abc为value
@Controller
public class HelloWorldController {
@ModelAttribute(value="attributeName")
public String addAccount(@RequestParam String abc) {
return abc;
}
@RequestMapping(value = "/helloWorld")
public String helloWorld() {
return "helloWorld";
}
}
(2)@ModelAttribute标注带返回具体值的方法,未指定key的名称,这个时候accountManager.findAccount(number) 返回的是Account类对象,那么默认将account(类的首写字母小写)作为key,返回的对象作为value
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountManager.findAccount(number);
}
(3)@ModelAttribute标注void返回值的方法 ,这个时候就需要我们自己手动的将数据添加到数据模型中
@Controller
public class HelloWorldController {
@ModelAttribute
public void populateModel(@RequestParam String abc, Model model) {
model.addAttribute("attributeName", abc);
}
@RequestMapping(value = "/helloWorld")
public String helloWorld() {
return "helloWorld";
}
}
2 @ModelAttribute注释一个方法的参数(第一步上将数据放在了对象模型mode里,那么如何数据如何拿出来用呢?)
把model里key为user的value赋值给helloWorld的参数user
@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";
}
}
@ModelAttribute 标记在处理器方法参数上的时候,表示该参数的值将从模型或者 Session 中取对应名称的属性值,该名称可以通过 @ModelAttribute(“attributeName”) 来指定,若未指定,则使用参数类型的类名称(首字母小写)作为属性名称。也就是上面的还可以这样写
@Controller
public class HelloWorldController {
@ModelAttribute("user")
public User addAccount() {
return new User("jz","123");
}
@RequestMapping(value = "/helloWorld")
public String helloWorld(@ModelAttribute User user) {
user.setUserName("jizhou");
return "helloWorld";
}
}
@SessionAttributes
在默认情况下,ModelMap 中的属性作用域是 request 级别是,也就是说,当本次请求结束后,ModelMap 中的属性将销毁。如果希望在多个请求中共享 ModelMap 中的属性,必须将其属性转存到 session 中,这样 ModelMap 的属性才可以被跨请求访问。
Spring 允许我们有选择地指定 ModelMap 中的哪些属性需要转存到 session 中,以便下一个请求属对应的 ModelMap 的属性列表中还能访问到这些属性。这一功能是通过类定义处标注 @SessionAttributes 注解来实现的。
@Controller
@RequestMapping ( "/myTest" )
@SessionAttributes (value={ "intValue" , "stringValue" }, types={User. class })
//@SessionAttributes("intValue") 只要求存intValue的时候可以写
//@SessionAttributes(types={User. class}) 只要求存类对象的时候可以这么写
public class MyController {
@ModelAttribute ( "hello" )
public String getModel() {
System. out .println( "-------------Hello---------" );
return "world" ;
}
@ModelAttribute ( "intValue" )
public int getInteger() {
System. out .println( "-------------intValue---------------" );
return 10;
}
@RequestMapping ( "sayHello" )
public void sayHello(Map<String, Object> map, @ModelAttribute ( "hello" ) String hello, @ModelAttribute ( "intValue" ) int num, @ModelAttribute ( "user2" ) User user, Writer writer, HttpServletRequest request) throws IOException {
map.put( "stringValue" , "String" );
writer.write( "Hello " + hello + " , Hello " + user.getUsername() + num);
writer.write( "\r" );
HttpSession session = request.getSession();
Enumeration enume = session.getAttributeNames();
while (enume.hasMoreElements())
writer.write(enume.nextElement() + "\r" );
System. out .println(session);
}
@ModelAttribute ( "user2" )
public User getUser() {
System. out .println( "---------getUser-------------" );
return new User(3, "user2" );
}
}
在上面代码中我们指定了属性为 intValue 或 stringValue 或者类型为 User 的都会放到 Session中,利用上面的代码当我们访问 /myTest/sayHello.do 的时候,结果如下:
Hello world,Hello user210
仍然没有打印出任何 session 属性,这是怎么回事呢?怎么定义了把模型中属性名为 intValue 的对象和类型为 User 的对象存到 session 中,而实际上没有加进去呢?难道我们错啦?我们当然没有错,只是在第一次访问 /myTest/sayHello.do 的时候 @SessionAttributes 定义了需要存放到 session 中的属性,而且这个模型中也有对应的属性,但是这个时候还没有加到 session 中,所以 session 中不会有任何属性,等处理器方法执行完成后 Spring 才会把模型中对应的属性添加到 session 中。所以当请求第二次的时候就会出现如下结果:
Hello world,Hello user210
user2
intValue
stringValue