美文网首页
redisTemplate,stringRedisTemplat

redisTemplate,stringRedisTemplat

作者: Eve0 | 来源:发表于2021-03-07 23:01 被阅读0次

    今天遇到一个奇怪的bug,就是redisTemplate获取不到值,而stringRedisTemplate可以获取得到,执行代码就是以下

    System.out.println(redisTemplate.opsForValue().get("name1"));
    System.out.println(stringRedisTemplate.opsForValue().get("name1"));
    

    debug打断点跟进去,DefaultValueOperations.java

    public V get(Object key) {
    
            return execute(new ValueDeserializingRedisCallback(key) {
    
                @Override
                protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
    //此处打开Evaluate Expression工具,计算rawKey.length=="name".getBytes().length,返回结果为false,可以定位问题在编码问题上
                    return connection.get(rawKey);
                }
            }, true);
        }
    

    继续debugger,可以到以下AbstractOperations.java

    // utility methods for the template internal methods
        abstract class ValueDeserializingRedisCallback implements RedisCallback<V> {
            private Object key;
    
            public ValueDeserializingRedisCallback(Object key) {
                this.key = key;
            }
    
            public final V doInRedis(RedisConnection connection) {
             //此处是将key序列化为byte[]的,继续跟到rawKey方法中
                byte[] result = inRedis(rawKey(key), connection);
                return deserializeValue(result);
            }
    
            @Nullable
            protected abstract byte[] inRedis(byte[] rawKey, RedisConnection connection);
        }
    

    继续跟到rawKey方法

    byte[] rawKey(Object key) {
    
            Assert.notNull(key, "non null key required");
    //继续跟keySerializer()
            if (keySerializer() == null && key instanceof byte[]) {
                return (byte[]) key;
            }
    
            return keySerializer().serialize(key);
    }
    

    恭喜找到源头了,这里获取的key的序列化对象。

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

    推理中,StringRedisTempate可以获取到值,来看一下这里面的一部分代码,看看是否有可参考性

    public StringRedisTemplate() {
            setKeySerializer(RedisSerializer.string());
            setValueSerializer(RedisSerializer.string());
            setHashKeySerializer(RedisSerializer.string());
            setHashValueSerializer(RedisSerializer.string());
    }
    

    同理找到RedisTemplate中类似的这段代码

    @Override
        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;
        }
    

    或者可以根据断点看到默认的Serializer是JdkSerializationRedisSerializer,与StringRedisTemplate中不一致。


    image.png

    解决:在自定义的RedisConfig中,参考StringRedisTemplate,将对应的几个序列化方法加入。

    @Configuration
    public class RedisConfig {
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            template.setKeySerializer(RedisSerializer.string());
            template.setValueSerializer(RedisSerializer.string());
            template.setHashKeySerializer(RedisSerializer.string());
            template.setHashValueSerializer(RedisSerializer.string());
            return template;
        }
    
    }
    

    相关文章

      网友评论

          本文标题:redisTemplate,stringRedisTemplat

          本文链接:https://www.haomeiwen.com/subject/xjduqltx.html