SpringBoot以及SpringMVC中@ModelAttribute注解的使用(结合@SessionAttributes)

@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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值