Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
SpringMVC教程
-> @SessionAttribute详解
1、Helloword
2、@Controller、@RequestMapping
3、接口测试利器
4、如何接受请求中的参数?
5、@RequestBody接收Json格式数据
6、多文件上传
7、返回页面常见的5种方式
8、返回json格式数据 & 通用返回值设计
9、SpringMVC返回null是什么意思?
10、异步处理请求
11、如何集成静态资源?
12、拦截器怎么用?
13、统一异常处理
14、实战篇:通用返回值 & 异常处理设计
15、全注解的方式 & 原理解析
16、源码解析SpringMVC处理请求的流程
17、源码解析SpringMVC容器的启动过程
18、RequestBodyAdvice:对@ReuqestBody进行增强
19、ResponseBodyAdvice:对@ResponseBody进行增强
20、RESTful接口详解
21、接口调用利器RestTemplate
22、参数解析器HandlerMethodArgumentResolver解密
23、@RequestParam用法及原理详解
24、@RequestBody原理解密
25、@RequestHeader详解
26、@CookieValue详解
27、@RequestAttribute详解
28、@SessionAttribute详解
29、重定向和转向详解
30、Converter转换器详解
31、跨域问题详解
32、类容协商,颠覆你的认知
33、终章
34、CORS通信
35、浏览器安全策略 & CORS
36、Http中的Content-Type详解
上一篇:@RequestAttribute详解
下一篇:重定向和转向详解
<div style="display:none"></div> **大家好,我是路人,这是SpringMVC系列第28篇。** 本文将介绍SpringMVC中的@SessionAttribute注解。 ## 1、预备知识 1. <a href="https://mp.weixin.qq.com/s/83zvde-O5PlI9Vd2nP_PZQ" target="_blank">接口测试利器 HTTP Client</a> 2. <a href="https://mp.weixin.qq.com/s/XQ1K4eXtGvfG_0RReFVg8Q" target="_blank">参数解析器HandlerMethodArgumentResolver解密</a> ## 2、@SessionAttribute注解 ### 2.1、作用 用来标注在接口的参数上,参数的值来源于session作用域。 ### 2.2、用法 如下代码,site参数上使用了`@SessionAttribute("site")`注解,site参数的值等于`session.getAttribute("site")` ```java @ResponseBody public String test2(@SessionAttribute("site") String site) { return site; } ``` 这个注解的源码如下 ```java @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SessionAttribute { /** * 指定session作用域中属性的名称 */ @AliasFor("name") String value() default ""; /** * 同value属性 */ @AliasFor("value") String name() default ""; /** * 属性是不是必须的,如果是true,session中没有取到时,则会抛出异常 * 此时可以将required设置为false,或者使用java8中的Option类型来修饰参数解决 */ boolean required() default true; } ``` ## 3、案例 下面代码中有2个接口方法 - 第一个方法test1中向session域中丢了一个site属性 - 第二个方的site参数上标注了`@SessionAttribute("site")`,所以会拿到session中site的值,然后输出 ```java package com.javacode2018.springmvc.chat18.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpSession; @Controller public class SessionAttributeController { @RequestMapping(value = "/sessionattribute/test1",produces = "text/html;charset=UTF-8") @ResponseBody public String test1(HttpSession session) { //向session中放入数据 session.setAttribute("site", "<a href='http://www.itsoku.com'>路人博客,包含了所有系列文章,阅读更方便</a>"); //重定向 return "session中放入了site信息!"; } @RequestMapping(value = "/sessionattribute/test2", produces = "text/html;charset=UTF-8") @ResponseBody public String test2(@SessionAttribute("site") String site) { return site; } } ``` 下面来验证一下效果。 浏览器中先访问第一个接口`/requestattribute/test1`,输出 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/239/fb4f3c10-01c3-49e3-9967-506edd685014.png) 然后再访问第二个接口`/requestattribute/test2`,输出如下,从session中拿到了site的值 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/239/a7a624b7-cf77-4ed2-ace2-45b2844861e1.png) 若我们调整一下接口1中代码,将site的值置为空 ```java request.setAttribute("site", null); ``` 此时再次访问接口(依次访问接口1和2),第2个接口会报400错误,原因:session域中没有找到site这个属性对应的值,即session.getAttribute("site")为null ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/239/e6b29d81-1715-4100-9d45-51509ba60d79.png) **2种解决方案** - 方案1:将@SessionAttribute的required属性设置为false,常用这种方式 - 方案2:将@SessionAttribute标注的参数类型调整为java8中的java.util.Optional类型,上面的接口2的site参数类型可以调整为`Optional<String>`类型,即可解决问题 ## 4、@SessionAttribute注解原理 @SessionAttribute注解标注的参数的值来源于`org.springframework.web.servlet.mvc.method.annotation.SessionAttributeMethodArgumentResolver`解析器,源码 ```java public class SessionAttributeMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(SessionAttribute.class); } @Override protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) { SessionAttribute ann = parameter.getParameterAnnotation(SessionAttribute.class); Assert.state(ann != null, "No SessionAttribute annotation"); return new NamedValueInfo(ann.name(), ann.required(), ValueConstants.DEFAULT_NONE); } @Override @Nullable protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) { return request.getAttribute(name, RequestAttributes.SCOPE_SESSION); } @Override protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException { throw new ServletRequestBindingException("Missing session attribute '" + name + "' of type " + parameter.getNestedParameterType().getSimpleName()); } } ``` ## 5、案例代码git地址 ```html https://gitee.com/javacode2018/springmvc-series ``` 所有系列文章的均在此仓库中。 <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
#custom-toc-container