Redis序列化的问题:Failed to deserialize object type
您好,我是码农飞哥,感谢您阅读本文!最近在进行框架改造,历史遗留代码对Redis的使用不当,导致了一些问题。
问题描述
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is org.springframework.core.NestedIOException: Failed to deserialize object type; nested exception is java.lang.ClassNotFoundException: com.coep.model.domain.UserCache
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.deserialize(JdkSerializationRedisSerializer.java:84)
- 1
- 2
从问题的描述我们就可以轻松的定位到这是由于调用JdkSerializationRedisSerializer的deserialize方法对redis值进行反序列化时报的错。
问题分析
错误提示是ClassNotFoundException: com.coep.model.domain.UserCache
,这个UserCache类找不到了,为啥找不到呢,这是由于我们在进行框架改造时变更了类的包名。所以,反序列化类时就找不到了。原有的对redis的操作类。
对redis使用的错误示范
private static RedisSerializer<Object> jdkRedisSerializer = new JdkSerializationRedisSerializer(); private static RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
public boolean set(final String key, final Object obj, final long seconds) { // key的组织形式 namespace:id:parmeter strRedisTemplate.execute((RedisCallback<Serializable>) connection -> { final byte[] keyBytes = stringRedisSerializer.serialize(key); final byte[] name = jdkRedisSerializer.serialize(obj); connection.setEx(keyBytes, seconds, name); return null; }); return true; } @Override public Serializable get(final Serializable key) { return strRedisTemplate.execute((RedisCallback<Serializable>) connection -> { byte[] keyBytes = stringRedisSerializer.serialize( key); byte[] bytes = connection.get(keyBytes); return (Serializable) jdkRedisSerializer.deserialize(bytes); }); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
这里设置键值时,对key使用的是StringRedisSerializer进行序列化,对value使用的是JdkSerializationRedisSerializer进行序列化。序列化后的数据类型是二进制的字节码文件,可视性差。而且使用JdkSerializationRedisSerializer序列化性能比较差,所以不推荐使用。
正确的姿势
对于历史的记录,只能在报错之后删除掉该key。这里推荐使用StringRedisSerializer来序列化key和value。相关的配置如下:
使用RedisTemplate操作类的配置如下:
@Primary @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { try { //测试连通性 factory.getConnection(); } catch (RedisConnectionFailureException e) { LOGGER.warn("未发现redis服务。"); redisAvailable = false; } RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new StringRedisSerializer()); redisTemplate.setConnectionFactory(factory); return redisTemplate; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
或者直接使用StringRedisTemplate操作类的配置如下:
@Bean public StringRedisTemplate stringRedisTemplate(JedisConnectionFactory redisConnectionFactory) { StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(redisConnectionFactory); return stringRedisTemplate; }
- 1
- 2
- 3
- 4
- 5
- 6
文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。
原文链接:feige.blog.csdn.net/article/details/113242603
- 点赞
- 收藏
- 关注作者
评论(0)