问题背景
- SpringBoot项目,整合了spring-boot-starter-data-redis
- 通过配置RedisTemplate来进行redis Key的增删查改操作
- 将对象存入redis成功(对象中还包含对象)
问题是:但是取出来的时候转成AuthInfo对象报错了!!!
异常如下:
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `com.zt.space.security.vo.JwtUser` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"["com.zt.}]"; line: 1, column: 331] (through reference chain: com.zt.space.security.vo.AuthInfo["jwtUser"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.zt.space.security.vo.JwtUser` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])")
at org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.deserialize(Jackson2JsonRedisSerializer.java:75)
...
原因
序列化原因!!!
解决方案
中途经历许多波折和探索,就不一一叙述了,直接上解决方案
第一步
先查看自己的RedisTemplate配置,有没有手动设置了序列化?
我也是参考另一篇博客的解答:Redis使用过程出现类型转换异常问题- 20190220
一看我自己的配置如下(网上照搬的。由此可见网上的东西坑货还是挺多的):
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
根据那篇博文的解释:RedisTemplate已经默认使用序列化了,我去看了下源码,还真是的,可能是以前的老版本不是。
所以根本不需要自己在手动设置,修改如下:
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
return template;
}
这个时候已经存取正常了
但是,人生总是会有意外惊喜
我去RDM中查看存的数据情况,如下:
完全无法查看json,感觉是乱码,但是实际上你通过java代码取出来的是正常的,只是无法通过RDM查看
初步估计是序列化的格式不对