@SessionAttributes 只能作用在类上,作用是将指定的Model中的键值对添加至session中,方便在下一次请求中使用。

简单示例

  • 目标是通过 @SessionAttributes 注解将Model中attrName为 "user","age","name" 的值添加至 session 中
 @Controller
@RequestMapping("/testSessionAttribute")
@SessionAttributes(value = {"user","age","name"})
public class TestSessionAttributeController { @ModelAttribute("user")
public User addUser(){
User user = new User();
user.setName("James");
user.setAge(29);
return user;
} @RequestMapping("/testHandler")
public String testHandler(Model model, String age, String name){
16 model.addAttribute("age",age);
17 model.addAttribute("name",name);
System.out.println(age);
System.out.println(name);
return "result";
}
}

对应的jsp代码如下:

 <body>
${sessionScope.user.age}
${sessionScope.user.name}
<br/>
${sessionScope.age}
${sessionScope.name}
</body>

通过实例可以得出一下结论:

  1. 不论是利用@ModelAttribute添加至model的数据,还是手动添加至model的数据,均遵循 @SessionAttributes 的规则

清除@SessionAttributes向session中添加的值

如果需要清除通过@SessionAttribute添加至 session 中的数据,则需要在controller 的 handler method中添加 SessionStatus参数,在方法体中调用SessionStatus#setComplete。

需要注意的是,此时清除的只是该Controller通过@SessionAttribute添加至session的数据(当然,如果不同controller的@SessionAttribute拥有相同的值,则也会清除)

@Controller
@RequestMapping("/testSessionAttribute")
@SessionAttributes(value = {"user","age","name"})
public class TestSessionAttributeController { .......................... @RequestMapping("/removeSessionAttributes")
public String removeSessionAttributes(SessionStatus sessionStatus){
sessionStatus.setComplete();
return "result";
}
}

通过@ModelAttributes和@SessionAttributes共同添加至session中的数据,只会添加一次

在没用使用SessionStatus清除过之前,通过@ModelAttributes和@SessionAttributes共同添加至session中的数据并不会更新,如下例:

 @Controller
@RequestMapping("/testSessionAttribute")
@SessionAttributes(value = {"user","age","name"})
public class TestSessionAttributeController { public static int age = 29;
@ModelAttribute("user")
public User addUser(){
User user = new User();
user.setName("James");
user.setAge(age++);
return user;
} @RequestMapping("/testHandler")
public String testHandler(Model model, String age, String name){
model.addAttribute("age",age);
model.addAttribute("name",name);
System.out.println(age);
System.out.println(name);
return "result";
} }
 <body>
${sessionScope.user.age}
${sessionScope.user.name}
<br/>
${sessionScope.age}
${sessionScope.name}
</body>

第一次请求:http://localhost:8080/testSessionAttribute/testHandler.action?name=James&age=29

结果:

29 James 
29 James

第二次请求:http://localhost:8080/testSessionAttribute/testHandler.action?name=James&age=30

29 James 
30 James

原因是,在org.springframework.web.bind.annotation.support.HandlerMethodInvoker#invokeHandlerMethod中进行了如下操作:

 public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception { Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
try {
boolean debug = logger.isDebugEnabled();
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
8 Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
9 if (attrValue != null) {
10 implicitModel.addAttribute(attrName, attrValue);
11 }
}
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
}
String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
20 if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
21 continue;
22 }
ReflectionUtils.makeAccessible(attributeMethodToInvoke);
Object attrValue = attributeMethodToInvoke.invoke(handler, args);
if ("".equals(attrName)) {
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
}
if (!implicitModel.containsAttribute(attrName)) {
implicitModel.addAttribute(attrName, attrValue);
}
}
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
if (debug) {
logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
}
ReflectionUtils.makeAccessible(handlerMethodToInvoke);
return handlerMethodToInvoke.invoke(handler, args);
}
catch (IllegalStateException ex) {
// Internal assertion failed (e.g. invalid signature):
// throw exception with full handler method context...
throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
}
catch (InvocationTargetException ex) {
// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
ReflectionUtils.rethrowException(ex.getTargetException());
return null;
}
}

如8-11行所示,在执行被@ModelAttributes注解的方法前,会将上一次通过@SessionAttributes添加至session中的数据添加添加至model中;

第20-22行,在执行被@ModelAttributes注解的方法前,springMVC会判断model中是否已经包含了@ModelAttributes给出的attrName,如果包含,则被@ModelAttributes注解的方法则不再执行

SpringMVC @SessionAttributes 使用的更多相关文章

  1. SpringMVC @SessionAttributes注解

    @SessionAttributes 注解只能作用到类上 @SessionAttributes(value={"user"},types={String.class}) @Sess ...

  2. SpringMVC SessionAttributes 简述

    使用SpringMVC时,我们会发现网络上有关SessionAttributes注解的内容非常少,更多的人甚至推荐你继续用HttpServletRequest中的session管理方法来控制Sessi ...

  3. SpringMVC @SessionAttributes 使用详解以及源码分析

    @sessionattributes @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Docum ...

  4. SpringMVC中的常用注解

    RequestParam 作用: 用于  将请求参数区数据  映射到  功能处理方法的参数上. 属性: value  请求参数中的名称 required   请求参数中是否必须提供此参数. 默认值: ...

  5. SpringMVC实例及注解(二)

    @RequestMapping()除了修饰方法,还可以修饰类1.类定义处:提供初步的请求映射信息.相对于WEB应用的根目录2.方法处:提供进一步的细分映射信息.相对于类定义处的URL.若类定义处未标注 ...

  6. Spring MVC 学习笔记(二)

    6. 视图和视图解析器  ❤  Spring MVC如何解析视图                                  • 请求处理方法执行完成后,最终返回一个ModelAndView对象 ...

  7. Spring MVC 学习笔记(一)

    • 1.SpringMVC概述 • 2.SpringMVC的HelloWorld • 3.使用@RequestMapping映射请求 • 4.映射请求参数&请求头 • 5.处理模型数据 • 6 ...

  8. 在SpringMVC中使用@SessionAttributes和@ModelAttribute将数据存储在session域中

    今天在我的springMVC项目--图书管理系统中,希望在登录时将登录的Users存在session中,开始是准备在controller中使用Servlet API中的对象,可是一直无法引用,不知道为 ...

  9. SpringMVC(十六) 处理模型数据之SessionAttributes

    @SessionAttributes原理 默认情况下Spring MVC将模型中的数据存储到request域中.当一个请求结束后,数据就失效了.如果要跨页面使用.那么需要使用到session.而@Se ...

随机推荐

  1. shell编程之函数

    一.函数定义和调用 函数是Shell脚本中自定义的一系列执行命令,一般来说函数应该设置有返回值(正确返回0,错误返回非0).对于错误返回,可以定义其他非0正值来细化错误.使用函数最大的好处是可避免出现 ...

  2. 深入浅出的webpack构建工具---DllPlugin DllReferencePlugin提高构建速度(七)

    阅读目录 一:什么是DllPlugin 和 DllReferencePlugin?作用是什么? 二:在项目中如何使用 DllPlugin 和 DllReferencePlugin? 三:DllPlug ...

  3. httpclient原理

    http.tcp/ip和socket的区别,用一个序列图概括最合适 网络上的跨域请求,都是以URL的方式发送请求,后端接收.标准的http请求格式包括header和body,传输到服务端 应用的协议都 ...

  4. [01] MyBatis概述

    传统的JDBC来做DAO层,做了下面这几件事: 加载驱动 获取连接 执行SQL语句 获取操作结果封装信息 返回操作结果 而实际上DAO层最关心的是什么呢,就是后面三点就完事,JDBC显得太繁琐: 执行 ...

  5. RocketMQ阅读注意

    1 队列个数设置 producer发送消息时候设置,特别注意:同一个topic仅当第一次创建的时候设置有效,以后修改无效,除非修改broker服务器上的consume.json文件,

  6. socket、tcp、udp、http 的认识及区别

    一.先来一个讲TCP.UDP和HTTP关系的 1.TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层. 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. 在传输 ...

  7. 将 C# 枚举序列化为 JSON 字符串 基础理论

    该转换过程需要引用 Newtonsoft.JSON,这其中的转换过程还是蛮有意思的. 一.定义枚举 /// <summary> /// 托寄物品枚举 /// </summary> ...

  8. 【下一代核心技术DevOps】:(三)私有代码库阿里云Git使用

    1. 引言 使用DevOps肯定离不开和代码的集成.所以要想跑通整套流程,代码库的选型也是非常重要的.否则无法实现持续集成.目前比较常用的代码管理有SVN和GIt 如果还使用SVN的,建议尽早迁移到G ...

  9. KVM虚拟机管理——资源调整

    1. 概述2. 计算资源调整2.1 调整处理器配置2.2 调整内存配置3. 存储资源调整3.1 根分区扩展3.2 添加磁盘4. 网络资源调整 1. 概述 KVM在使用过程中,会涉及到计算(CPU,内存 ...

  10. 关于用tesseract和tesserocr识别图片的一个问题

    对于像我这样初学python网络爬虫的freshman来说,软件的准备和环境的配置能让我们崩溃.其中用刚安装好的tesseract和tesserocr库测试识别验证码就是其中一例. 这里我要测试的验证 ...