>>分享流行的Java框架以及开源软件,对孙卫琴的《精通Spring》、《Spring Cloud Alibaba微服务开发零基础入门到实操》提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 24751 个阅读者 刷新本主题
 * 贴子主题:  @SessionAttributes的用法 回复文章 点赞(0)  收藏  
作者:flybird    发表时间:2020-07-01 20:02:54     消息  查看  搜索  好友  邮件  复制  引用

@SessionAttributes 只能作用在类上,作用是将指定的Model中的键值对添加至session中,方便在下一次请求中使用。
简单示例
目标是通过 @SessionAttributes 注解将Model中attrName为 "user","age","name" 的值添加至 session 中
1 @Controller
2 @RequestMapping("/testSessionAttribute")
3 @SessionAttributes(value = {"user","age","name"})
4 public class TestSessionAttributeController {
5
6     @ModelAttribute("user")
7     public User addUser(){
8         User user = new User();
9         user.setName("James");
10         user.setAge(29);
11         return user;
12     }
13
14     @RequestMapping("/testHandler")
15     public String testHandler(Model model, String age, String name){
16         model.addAttribute("age",age);
17         model.addAttribute("name",name);
18         System.out.println(age);
19         System.out.println(name);
20         return "result";
21     }
22 }

对应的jsp代码如下:

1 <body>
2     ${sessionScope.user.age}
3     ${sessionScope.user.name}
4     <br/>
5     ${sessionScope.age}
6     ${sessionScope.name}
7 </body>

通过实例可以得出一下结论:
不论是利用@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中的数据并不会更新,如下例:

1 @Controller
2 @RequestMapping("/testSessionAttribute")
3 @SessionAttributes(value = {"user","age","name"})
4 public class TestSessionAttributeController {
5
6     public static int age = 29;
7     @ModelAttribute("user")
8     public User addUser(){
9         User user = new User();
10         user.setName("James");
11         user.setAge(age++);
12         return user;
13     }
14
15     @RequestMapping("/testHandler")
16     public String testHandler(Model model, String age, String name){
17         model.addAttribute("age",age);
18         model.addAttribute("name",name);
19         System.out.println(age);
20         System.out.println(name);
21         return "result";
22     }
23
24 }

JSP代码

1 <body>
2     ${sessionScope.user.age}
3     ${sessionScope.user.name}
4     <br/>
5     ${sessionScope.age}
6     ${sessionScope.name}
7 </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中进行了如下操作:

1 public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
2             NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
3
4         Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
5         try {
6             boolean debug = logger.isDebugEnabled();
7             for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
8                 Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
9                 if (attrValue != null) {
10                     implicitModel.addAttribute(attrName, attrValue);
11                 }
12             }
13             for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
14                 Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
15                 Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
16                 if (debug) {
17                     logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
18                 }
19                 String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
20                 if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
21                     continue;
22                 }
23                 ReflectionUtils.makeAccessible(attributeMethodToInvoke);
24                 Object attrValue = attributeMethodToInvoke.invoke(handler, args);
25                 if ("".equals(attrName)) {
26                     Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
27                     attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
28                 }
29                 if (!implicitModel.containsAttribute(attrName)) {
30                     implicitModel.addAttribute(attrName, attrValue);
31                 }
32             }
33             Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
34             if (debug) {
35                 logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
36             }
37             ReflectionUtils.makeAccessible(handlerMethodToInvoke);
38             return handlerMethodToInvoke.invoke(handler, args);
39         }
40         catch (IllegalStateException ex) {
41             // Internal assertion failed (e.g. invalid signature):
42             // throw exception with full handler method context...
43             throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
44         }
45         catch (InvocationTargetException ex) {
46             // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
47             ReflectionUtils.rethrowException(ex.getTargetException());
48             return null;
49         }
50     }

  如8-11行所示,在执行被@ModelAttributes注解的方法前,会将上一次通过@SessionAttributes添加至session中的数据添加添加至model中;
第20-22行,在执行被@ModelAttributes注解的方法前,springMVC会判断model中是否已经包含了@ModelAttributes给出的attrName,如果包含,则被@ModelAttributes注解的方法则不再执行


程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->流程控制
  JavaWeb开发-->开发JavaMail Web应用
  JSP与Hibernate开发-->立即检索和延迟检索策略
  Java网络编程-->通过JavaMail API收发邮件
  精通Spring-->
  Vue3开发-->Vue CLI脚手架工具
  Maven 安装及环境配置
  教你手撸一个Spring框架,从Spring.xml解析到注册Bean对象!
  SpringCloud服务间内部调用原理
  如何编写优雅的Spring架构API
  微服务的拆分方式
  Spring MVC文件上传与下载
  使用Spring MVC处理404错误的方法
  Spring的方法拦截器范例
  vue父、子组件相关的传递
  SpringMVC Model、ModelMap和ModelAndView的区别和用法
  RESTful API的最佳设计原则
  Spring Boot集成EHCache实现缓存机制
  另一种缓存,Spring Boot 整合 Ehcache
  Spring Cloud 服务发布与调用
  Spring Boot集成shiro ehcache(使用shiro的缓存管理)
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。