日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【身份认证与控制二】分布式session共享(序列化问题)

發布時間:2024/10/5 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【身份认证与控制二】分布式session共享(序列化问题) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 在首次獲取session后,將sessionid作為鍵將對應session域信息序列化后保存到redis數據庫內
  • 需要獲取session域信息時,拿著request攜帶的cookie中的sessionId值向redis數據庫查找對應的數據,并反序列化為Session對象
  • ?

    /*** 保存session** @param req 請求信心* @return 結果*/@GetMapping("/saveSession")public AjaxResult saveSession(HttpServletRequest req){System.out.println(new Date()+":::"+req.getSession().getId());HttpSession session = req.getSession();session.setAttribute("num",num++);String sessionString = JSON.toJSONString(session);redisFullUtil.set(session.getId(),sessionString);return AjaxResult.success(session.getId()+"::"+session.getAttribute("num"));}/*** 獲取保存的session** @param req 請求信息* @return 結果*/@GetMapping("/getSession")public AjaxResult getSession(HttpServletRequest req){System.out.println(new Date()+":::"+req.getSession().getId());String sessionString = redisFullUtil.get(req.getSession().getId());HttpSession session = JSON.parseObject(sessionString, HttpSession.class);return AjaxResult.success(session.getAttribute("num"));}

    程序運行后直接報錯

    com.alibaba.fastjson.JSONException: illegal setter

    ?原因是redis序列化依賴于set和get方法,session中有些數據屬性是沒有的,

    spring-session-data-redis

    轉變思路一番搜索,現有技術是如何實現session分離,發現spring-session-data-redis就是專門做這件事的,還幫我們完成了大部分的工作,只需要做一些簡答的配置工作即可完成session的分離

    1. pom引入依賴

    <!-- spring boot 與 redis 應用的基本配置 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency><!-- spring session 與redis 應用環境基本配置, 需要開啟redis后才可以使用, 不然啟動會報錯 --> <dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId> </dependency>

    2. 配置: application.yml

    spring:redis:database: 0host: 你的redisipport: 6379password: 你的redis密碼pool:max-idle: 8min-idle: 0max-active: 8max-wait: 1timeout: 5000session:store-type: redisredis:hostname: 你的redisipport: 6379pawssword: 你的redis密碼

    3. 增加配置類

    SessionConfig.Class

    package org.huber.sharesession.config;import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; import org.springframework.session.web.http.DefaultCookieSerializer;import javax.validation.Valid;/*** @Classname SessionConfig* @Description TODO* @Date 2020/1/17 12:43* @Author by Ren Jie*/ @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) public class SessionConfig {@Value("{$redis.hostname}")private String hostName;@Value("${redis.port}")private int port;@Beanpublic RedisStandaloneConfiguration connectionFactory() {RedisStandaloneConfiguration jedisConnectionFactory = new RedisStandaloneConfiguration();jedisConnectionFactory.setHostName(hostName);jedisConnectionFactory.setPort(port);return jedisConnectionFactory;}@Beanpublic DefaultCookieSerializer defaultCookieSerializer(){DefaultCookieSerializer defaultCookieSerializer = new DefaultCookieSerializer();defaultCookieSerializer.setCookiePath("/");return defaultCookieSerializer;} }

    核心就在這個反序列化上?

    package org.huber.sharesession.config;import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;/*** @Classname SessionInitializer* @Description TODO* @Date 2020/1/17 12:47* @Author by Ren Jie*/ public class SessionInitializer extends AbstractHttpSessionApplicationInitializer {public SessionInitializer(){super(SessionConfig.class);} }

    結果測試

  • 開啟會話,獲取sessionid
  • 重啟服務器
  • 再次訪問后臺,獲取sessionid
    如果是同一個sessionid,則說明session分離成功
  • package org.huber.sharesession.controller;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;/*** @Classname SessionController* @Description TODO* @Date 2020/1/17 12:49* @Author by Ren Jie*/ @RestController @RequestMapping("/shareSession/session") public class SessionController {@GetMapping("/setSession")public String setSession(HttpServletRequest req){String sessionId = req.getSession().getId();System.out.println("sessionId = " + sessionId);return sessionId;} }

    演示如下:
    ?

    完了還是可能有問題:

    我們來看看redis的序列化:

    對redis進行配置,實現發序列化,因為reids序列化已經實現了,這里就不用再對序列化進行研究了(redis序列化見文章:DefaultSerializer requires a Serializable payload but received an object of type [select.system.dto.User] - 葉語婷 - 博客園)。

    這里對key和value分別進行反序列化,進而在redis中生成字符型的key和對象型value。

    /*** @author yeyuting* @create 2021/2/19*/ @Configuration public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();RedisSerializer<String> redisSerializer = new StringRedisSerializer();template.setConnectionFactory(factory);//key序列化方式template.setKeySerializer(redisSerializer);//value序列化template.setValueSerializer(new JdkSerializationRedisSerializer());//value hashmap序列化template.setHashValueSerializer(redisSerializer);//key haspmap序列化template.setHashKeySerializer(redisSerializer);return template;}}

    執行后redis中是這樣的

    ?可知,key反序列話成功了,但是value對象反序列化失敗了,接著就將注意力轉移到value對象的反序列化中來。

    當我們的數據存儲到Redis的時候,我們的鍵(key)和值(value)都是通過Spring提供的Serializer序列化到數據庫的。RedisTemplate默認使用的是JdkSerializationRedisSerializer,StringRedisTemplate默認使用的是StringRedisSerializer。?用JdkSerializationRedisSerializer序列化的話,被序列化的對象必須實現Serializable接口。在存儲內容時,除了屬性的內容外還存了其它內容在里面,總長度長,且不容易閱讀。我們要求是存儲的數據可以方便查看,也方便反系列化,方便讀取數據。JacksonJsonRedisSerializer和GenericJackson2JsonRedisSerializer,兩者都能系列化成json,但是后者會在json中加入@class屬性,類的全路徑包名,方便反系列化。前者如果存放了List則在反系列化的時候如果沒指定TypeReference則會報錯java.util.LinkedHashMap cannot be cast to 。

    因此保險起見,我們將JdkSerializationRedisSerializer換成GenericJackson2JsonRedisSerializer,修改后的代碼如下:

    /*** @author yeyuting* @create 2021/2/19*/ @Configuration public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();RedisSerializer<String> redisSerializer = new StringRedisSerializer();template.setConnectionFactory(factory);//key序列化方式template.setKeySerializer(redisSerializer);//value序列化template.setValueSerializer(new GenericJackson2JsonRedisSerializer());//value hashmap序列化template.setHashValueSerializer(redisSerializer);return template;}}

    執行后redis緩存內容正常顯示,如下:

    原理就是將httpSession替換成自己實現的httpsession

    參考:1、Redis應用:session分離 【session序列化失敗 JSONException異常 spring-session-data-redis實現】_奮斗zhe的博客-CSDN博客

    ?2、Java簡單實現session保存到redis的方法示例_李修睿的博客-CSDN博客_java session存入redis

    3、?

    總結

    以上是生活随笔為你收集整理的【身份认证与控制二】分布式session共享(序列化问题)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。