SpringBoot项目使用RedisTemplate设置序列化方式

前端时间新项目使用 SpringBoot 的 RedisTemplate 遇到一个问题,先简单描述一下问题:不同项目之间 redis 共用一个,但是我们新项目读不到老项目存储的缓存。新项目搭建的时候没有跟老项目使用同一个 core 包里的 redisutils 工具类,老项目使用的是 jedis 对象来操作 redis,新项目使用了 springboot 封装的 redistemplate,代码上存在差异所以出现问题也就很正常,先来看一下新项目里对 redistemplate 的使用:(截取一个方法为例)

现象

1732556-20191112163503790-1028953676.png

可以看出来工具直接注入 spring 容器中的 redistemplate,没有指定泛型,在使用的时候通过 key 的泛型使用的是 Serializable,value 的泛型是 value,从泛型能看出来 key 跟泛型有一定关系,下面就来验证一下为什么取不到值。我们先往 redis 里存储一个缓存以字符串为例:

1732556-20191112171103610-747777381.png

写一个 junit 测试 
1732556-20191112171317029-1685933414.png

测试取缓存
1732556-20191112171801507-1908588084.png

通过结果发现没有取到值,反过来通过测试方法存一下缓存,再看我们存的是一个什么值
1732556-20191112174227685-290848160.png

通过结果发现我们存进去的 key 是 redistemplate-test,但是 redis 实际存进去的 key 却是 xacxedx00x05tx00x12redistemplate-test,同理,我们取缓存的时候前面也会自动加上一串看不懂的东西,所以取值的时候肯定也取不出来。做项目的时候时间比较紧,用了其他同事的代码保证项目上线,上线后才回过头去看取不到值的原因,其实同事的代码也很简单,只是在使用 redistemplate 的时候指定了泛型为 string,就可以取到值了,其实也可以使用 StringRedisTemplate 来操作,但是 StringRedisTemplate 主要用来存储字符串,它的泛型指定的是 String。如果存入对象时,会报错 :can not cast into String,所以我们就继续修改这个工具,解决 key 值前面的字符串。

原因

下面我们简单的看一下 redistemplate 源码
1732556-20191113103216778-1052938570.png

opsForValue 方法会返回一个 ValueOperations<K, V>,k 跟 v 就是泛型,我们就是通过 valueOps 来 get,set 我们的值。这个方法会 new 一个 DefaultValueOperations 对象,传入的 template 就是当前 RedisTemplate 对象,向下看:
1732556-20191113103920957-59051634.png
1732556-20191113115601132-657040362.png

有很多个 RedisSerializer,默认都是 null,当调用 opsForValue 方法时会传入当前 redistemplate 对象,以 keySerializer 为例,它默认为 null,如果等于 null 就被赋值 dafaultSerializer,默认 dafaultSerializer 也为空,最终 keySerializer 就被赋值为 JdkSerializationRedisSerializer,所以没有设置序列化方式的时候 redistemplate 使用的序列化方式为 JdkSerializationRedisSerializer,所以我们存入 key 前面会带上一串东西,而 StringRedisTemplate 使用的是 StringRedisSerializer,序列化的方式不一样,所以使用的时候 key 就不会出现一串字符串。

解决方案
简单了解原因后,现在就来解决这个问题,解决问题的方法就是设置序列化方式

1732556-20191114182634492-1285225508.png

这样解决了上面的问题。问题倒不难,只是自己以前没有遇到过,不知道这个方法是同事从网上直接复制的还是同事自己写的,只能说复制的时候不够严谨,没有考虑到项目的实际情况,这个问题其实只要拿出一块时间去看看代码,查查资料就能解决,所以遇到问题的时候一定要找到原因去解决问题,而不是把问题隐藏掉。

评论已关闭