为了账号安全,请及时绑定邮箱和手机立即绑定

Spring MVC SessionAttributes ModelAttribute注解

标签:
Java

说明

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

 

@SessionAttributes

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

 属性

    ① value:

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

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

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

    ③ type:

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

 属性对应源码

    https://img1.sycdn.imooc.com//5b65d09c0001ec9d09040081.jpg

 用法

    注意:@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";
    }
}

复制代码

     页面显示:

     https://img1.sycdn.imooc.com//5b65d0a8000179f905740073.jpg

 

    注意: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 中的每个方法执行之前都执行一次。

    ① 修饰没有返回值的方法

      https://img1.sycdn.imooc.com//5b65d0b000018da405390101.jpg

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

      https://img1.sycdn.imooc.com//5b65d0b90001182003900101.jpg

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

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

       https://img1.sycdn.imooc.com//5b65d0ee0001e65702480050.jpg

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

      https://img1.sycdn.imooc.com//5b65d0fc0001cd8005880147.jpg

    执行该方法就会向 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;
    }

复制代码

    上面方法输出内容如下:

    https://img1.sycdn.imooc.com//5b65d1120001b89304550049.jpg

    这里输出的内容就是我们上面 做修饰有返回值方法时放入的值。那么, @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";
    }
}

复制代码

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

原文出处:https://www.cnblogs.com/dream-saddle/p/9405032.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消