一、问题描述:
执行代码:
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缓存内容正常显示,如下:
至此,结束。