一、問題描述:
執行代碼:
valueOperations.set(user1.getUserName() , user1);
將對象存入redis,存入后變成了如下所示的樣子。
二、原因分析
我們首先在實體類中實現了序列化接口,這時,User對象序列化為了字節流,傳輸進入redis,但是在進入redis反序列化為key和value對象的時候發生了錯誤,因此這里出現此問題是因為redis的反序列化失敗,這時我們就主要圍繞redis反序列化失敗進行研究。
三、解決方案
對redis進行配置,實現發序列化,因為reids序列化已經實現了,這里就不用再對序列化進行研究了(redis序列化見文章:https://www.cnblogs.com/yeyuting/p/14414736.html)。
這里對key和value分別進行反序列化,進而在redis中生成字符型的key和對象型value。
/** * @author yeyuting * @create 2021/2/19 */ @Configuration public class RedisConfig { @Bean public 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 { @Bean public 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緩存內容正常顯示,如下:
至此,結束。