今天在测试springboot整合redis的时候遇到下面这个坑,百度来百度去发现提示都是ajax的问题,真的是醉了,错误提示如下所示,不信大家可以直接复制百度一下答案是什么(流泪中。。。。),错误如下:
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unrecognized token 'b4811c63': was expecting ('true', 'false' or 'null')
1.错误原因排查
然后就进行debug调试,发现代码一直到redisTemplate.opsForZSet().reverseRangeWithScores()这一行都没问题,然后进入redis源代码里面检查,发现是在发送redis服务的时候出现问题,所以可以断定应该是配置的问题,然后仔细检查配置,发现也没有错误,redis序列化的配置如下所示:
@Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new StringRedisTemplate(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); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; }
2.细节分析
这一条线索断掉之后,只能通过错误信息来分析了,错误信息中有一条特别奇怪,就是token 'b4811c63',然后我仔细从redis中对比,发现是之前存储的redis的key值,判断可能是redis中key存在乱码,所以就将redis的key全部清空,自己添加数据进去,发现自己添加的数据是可以的。从这一现象可以得出,应该实现老系统序列化的规则和现在springboot的序列化规则不一样导致的,查看老系统的redis配置信息,如下所示:
<!--序列化--> <bean name="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/> <bean name="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> <bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="redis4CacheConnectionFactory"/> <property name="keySerializer" ref="stringRedisSerializer"/> <property name="hashKeySerializer" ref="stringRedisSerializer"/> <property name="valueSerializer" ref="stringRedisSerializer"/> <property name="hashValueSerializer" ref="stringRedisSerializer"/> </bean>
3.问题解决
然后和我们刚才序列化的方式对比一下,发现真的是序列化方式不一样,旧的是通过StringRedisSerializer进行序列化的,springboot是通过Jackson2JsonRedisSerializer进行序列化的。所以为了兼容老系统的序列化方式,这边我将springboot也改成StringRedisSerializer的序列化方式,代码如下所示:
@Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate redisTemplate = new StringRedisTemplate(factory); StringRedisSerializer stringRedisSerializer =new StringRedisSerializer(); redisTemplate.setValueSerializer(stringRedisSerializer); redisTemplate.setKeySerializer(stringRedisSerializer); redisTemplate.setHashKeySerializer(stringRedisSerializer); redisTemplate.setHashValueSerializer(stringRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; }
改完之后,发现这个问题就没有了,redis中就可以照常插入、查询数据了。
总结:
这个问题是很典型的架构优化问题,老系统和新系统代码兼容性问题。从这个坑可以得出这样的结论:百度得到的答案很大一部分都是片面的,我们还是得根据实际情况来分析。其次就是要仔细看报错信息,不要放过一点细节,因为可能你的答案就在这一点细节中。