一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

解决RedisTemplate的key默认序列化器问题代码示例

时间:2021-03-02 编辑:袖梨 来源:一聚教程网

本篇文章小编给大家分享一下解决RedisTemplate的key默认序列化器问题代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看。

redis的客户端换成了spring-boot-starter-data-redis,碰到了一个奇怪的问题,

在同一个方法中

1.先hset,再hget,正常获得数据。

在不同的方法中 先hset,再hget获取不到数据,通过redis的monitor监控发现了命令的问题:

实际我的key为JK_HASH:csrk,hashkey为user,但是根据上图所示,实际执行的命令多了好多其他字符,这是什么原因呢?

在服务器端先确认发现实际有这个Hash,通过hset可以得到正确的数据,所以第一次执行hset的时候命令是正常的,问题可能出现在hget上面,先打开源码看一下

 @SuppressWarnings("unchecked")
 public HV get(K key, Object hashKey) {
 final byte[] rawKey = rawKey(key);
 final byte[] rawHashKey = rawHashKey(hashKey);
 
 byte[] rawHashValue = execute(new RedisCallback() {
 
 public byte[] doInRedis(RedisConnection connection) {
 return connection.hGet(rawKey, rawHashKey);
 }
 }, true);
 
 return (HV) deserializeHashValue(rawHashValue);
 }

从这里可以看到实际上传给redis的都是byte数据,而byte数组是rawKey和rawHashKey生成的,先看下rawKey方法

 @SuppressWarnings("unchecked")
 byte[] rawKey(Object key) {
 Assert.notNull(key, "non null key required");
 if (keySerializer() == null && key instanceof byte[]) {
 return (byte[]) key;
 }
 return keySerializer().serialize(key);
 }

然后进一步跟踪keySerializer()方法

 RedisSerializer keySerializer() {
 return template.getKeySerializer();
 }
 public RedisSerializer getKeySerializer() {
 return keySerializer;
 }

最后跟踪到是RedisTemplate中的属性keySerializer导致的,而通过打印keySerializer的class发现 默认使用的是org.springframework.data.redis.serializer.JdkSerializationRedisSerializer,但它是如何进行初始化的呢,默认的构造函数中并没有对该属性进行初始化。

根据RedisTemplate的类关系发现它是继承RedisAccessor的,而此类是实现的org.springframework.beans.factory.InitializingBean接口,这个接口有个特性,凡是继承该接口的类,在初始化bean的时候会执行afterPropertiesSet方法。

而afterPropertiesSet方法中,确实对keySerializer进行了初始化:

 public void afterPropertiesSet() {
 super.afterPropertiesSet();
 boolean defaultUsed = false;
 if (defaultSerializer == null) {
 defaultSerializer = new JdkSerializationRedisSerializer(
 classLoader != null ? classLoader : this.getClass().getClassLoader());
 }
 if (enableDefaultSerializer) {
 if (keySerializer == null) {
 keySerializer = defaultSerializer;
 defaultUsed = true;
 }
 if (valueSerializer == null) {
 valueSerializer = defaultSerializer;
 defaultUsed = true;
 }
 if (hashKeySerializer == null) {
 hashKeySerializer = defaultSerializer;
 defaultUsed = true;
 }
 if (hashValueSerializer == null) {
 hashValueSerializer = defaultSerializer;
 defaultUsed = true;
 }
 }
 if (enableDefaultSerializer && defaultUsed) {
 Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
 }
 if (scriptExecutor == null) {
 this.scriptExecutor = new DefaultScriptExecutor(this);
 }
 initialized = true;
 }

在这里可以看到默认使用的正是org.springframework.data.redis.serializer.JdkSerializationRedisSerializer,而问题正在这里,通过查询可以发现序列化器有这些,而在这里我们需要使用的是StringRedisSerializer

加入如下代码:

 @Autowired(required = false)
 public void setRedisTemplate(RedisTemplate redisTemplate) {
  RedisSerializer stringSerializer = new StringRedisSerializer();
  redisTemplate.setKeySerializer(stringSerializer);
  redisTemplate.setValueSerializer(stringSerializer);
  redisTemplate.setHashKeySerializer(stringSerializer);
  redisTemplate.setHashValueSerializer(stringSerializer);
  this.redisTemplate = redisTemplate;
 }

重新进行测试,方法1hset,方法2hget,方法2能拿到正确的数据,完毕。

热门栏目