Spring MVC SessionAttributes ModelAttribute注解

说明

  本文主要针对 @SessionAttributes注解 和 @ModelAttribute注解的基础用法进行解析。至于为什么会将这两个注解放在一起,是因为它们之间还是有点影响的。

@SessionAttributes

  光看这个注解的名字大概也就知道这个注解是用于往 Session 域中存数据的吧!这个注解是 Spring2.5版本才有的。

 属性

    ① value:

      一个字符串数组,表示存放到 Session 域中的属性名

    ② names: (这个属性是 4.2版本才有的)

      和 value 属性一样,他们之间是彼此的别名而已

    ③ type:

      一个 Class 数组,根据指定的类型,将模型中对应类型的数据放到 Session 域中

 属性对应源码

    

 用法

    注意:@SessionAttributes 注解只能用在类上面。

    

package com.test;

import *;

@Controller
@SessionAttributes(value={"name", "age"}, types={String.class})    //value 换成 names 一样的效果
public class SessionAttribute {

    @RequestMapping("/testSessionAttribute1")
    public String testSessionAttribute1(Map<String, Object> map) {
        //name 属性被放入了 value 数组中,所以也就存入了 Session 域中
        map.put("name", "张三");
        //age 属性放入了 names 数组中,也一样存入了 Session 域中
        map.put("age", 19);
        //由于 types 数组中有 String.class,所以,address 属性也会放入 Session 域中
        map.put("address", "重庆市");
        
        return "success";
    }
}

     页面显示:

     

    注意:value 属性不能和 names 属性一起使用,如果一起使用了会出现下面异常信息

org.springframework.core.annotation.AnnotationConfigurationException: In annotation [org.springframework.web.bind.annotation.SessionAttributes] declared on class com.test.SessionAttribute and synthesized from [@org.springframework.web.bind.annotation.SessionAttributes(names=[age], value=[name], types=[class java.lang.String])], attribute 'names' and its alias 'value' are present with values of [{age}] and [{name}], but only one is permitted.

@ModelAttribute

  修饰方法

    注意:有 @ModelAttribute 注解修饰的方法,会在 Controller 中的每个方法执行之前都执行一次。

    ① 修饰没有返回值的方法

      

    上面这个方法被 @ModelAttribute 注解所修饰,且没有返回值。但是,在方法的入参处有一个 map 集合,且在方法内部向 mpa 中放入了一个键值对。

      

    执行完了 isNotReturn() 方法后,就会接着来到 isNotReturnTest() 方法,该方法重定向到了 success.jsp 页面,那么,map 集合中存放的数据也会在 request 域中被带到页面上。

    最后从 request 域中获取 tom,页面输出:

       

    上面两个方法可合并为一个方法:

      

    执行该方法就会向 map 中放入一个键值对,并且转发到 success.jsp 页面,且将数据通过 request 域带到页面。

    ② 修饰有返回值的方法

  //修饰有返回值的方法
    @ModelAttribute(value="argtest")
    public String havaArg(Map<String, Object> map, Model model) {
        /*
         * 下面这种情况,返回值会被默认放到隐藏的 Model 中,在 Model 中的 key默认为 返回值的首字母小写,
         * 可以通过 ModelAttribute 注解的 value 属性设置
         * value 为返回的值
         * model.addAttribute("string", "值");
         */
        //map.put("arg", "修饰有返回值的方法");
        model.addAttribute("modelTest", "model 测试");
        
        return "修饰有返回值的方法";
    }

    注释中已经说的很清楚了,上面方法中,返回了一个字符串,那么在 model 中就会以下面的方式将 这个字符串存入 model:

    model.addAttribute("string", 修饰有返回值的方法");

    由于默认以返回值的首字母小写作为 key,这样可定有一定局限性,所以我们可以再 @ModelAttribute 注解中加上 value 属性标明返回值在 model 中的 key,还是上面的例子来说,加上 value 属性值后就是

    model.addAttribute("argtest", 修饰有返回值的方法");

  

  修饰参数

  //修饰参数,就是从 Model 中获取对应的属性值
    @RequestMapping("/updateUserInfo")
    public String updateUserInfo(User user, 
            @ModelAttribute("modelTest") String modelTest, 
            @ModelAttribute(value="argtest") String argtest) {
        
        System.out.println("ModelAttribute修改参数:"+modelTest);
        System.out.println("ModelAttribute修改参数:"+argtest);
        
        return SUCCESS;
    }

    上面方法输出内容如下:

    

    这里输出的内容就是我们上面 做修饰有返回值方法时放入的值。那么, @ModelAttribute 注解修饰参数就代表从 Model 中获取对应属性名的值。

  修饰被 @RequestMapping 注解修饰的方法

   @RequestMapping("/test2")
    @ModelAttribute
    public String test2() {
        System.out.println("修饰有 RequestMapping修饰的方法");
        
     //这里返回的 "success" 就不在代表视图了,而是 RequestMapping 注解的 value 属性值才代表视图
return SUCCESS; }

   可见上面 test2() 方法上有两个注解,那么,这个方法就不会在每次访问 Controller 时都会执行了。因为不是每次执行 Controller 都会执行该方法,所以,返回的 "success"字符串也不会被放入 Model 中(就会是一个无效的操作)。同时,返回值 "success" 也不代表视图,此时对应的页面就是 RequestMapping 注解对应的值 "test2",所以,在访问 "/test2" 来到 test2() 方法后,返回回去的路径为 test2.jsp,由于没有该页面,出现 404。

上面内容讲解了 SessionAttributes 注解和 ModelAttribute 注解各自的基本用法,下面就来看看他俩放在一起使用可能会出现什么问题

SessionAttributes 注解和 ModelAttribute 注解一起使用

  情况一

@Controller
@SessionAttributes(value= {"name"})
public class Test {
    
     //执行该 方法后,会将 name属性放入 Model 中和 Session 中
   //只要 ModelAttribute 属性值和 SessionAttributes 注解 value 属性其中一个属性值一致,那么,ModelAttribute 修饰方法返回值也会被放入 Session 中
@ModelAttribute("name") public String getName() { return "李四"; } }

   情况二

import *;

@Controller
@SessionAttributes(value= {"userInfo"})
public class Test {/* 这段代码什么意思:     页面上存在一个表单,当点击提交后,整个表单中的数据就会自动封装为一个 UserInfo 对象,并传递到 Handler 方法中,输出,最后跳转到 "success.jsp" 页面,同时将 UserInfo 对象    放到 Session 域中 */ @RequestMapping("/test2") public String test2(@ModelAttribute("userInfo") UserInfo userInfo) { System.out.println("修改方法:"+userInfo); return "success"; } }

  但是,上面代码执行会出错的。会抛出下面异常信息:

 org.springframework.web.HttpSessionRequiredException: Expected session attribute 'userInfo'  //Session 中不存在 userInfo 属性

  解决办法

  一、将 目标方法 即代码中 test2() 方法 的 @ModelAttribute("userInfo") 中的 userInfo 改名,只要不和 SessionAttributes 注解中的名字一样就可以了。

  二、目标方法 即代码中 test2() 方法 的 @ModelAttribute("userInfo") 去掉,添加一个对应的被 ModelAttribute 修饰的方法。

import *;

@Controller
@SessionAttributes(value= {"userInfo"})
public class Test {
    @ModelAttribute
    public void getUserInfo(UserInfo userInfo, Model model) {
        model.addAttribute("userInfo", userInfo);
    }

@RequestMapping("/test2") public String test2(UserInfo userInfo) { System.out.println("修改方法:"+userInfo); return "success"; } }

  这里只做了一个简单的处理介绍,关于更详细的原因,我会在后面说明。还得下去多了解一下源码过程!

猜你喜欢

转载自www.cnblogs.com/dream-saddle/p/9405032.html
今日推荐