zoukankan      html  css  js  c++  java
  • redis

    Spring Data操作Redis时,发现key值出现 xacxedx00x05tx00 b

    先说现象吧,通过redisTemplate下的opsForHash方法存储hash类型的值,操作成功以后,去redis控制台显示keys * 的时候,发现一个奇怪的现象,插入的hash类型的key前面会有一堆的xacxedx00x05tx00 b 这种东西,见图1:

     分析spring-data的org.springframework.data.redis.core.RedisTemplate源代码以后发现:

    private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();
     
        private RedisSerializer keySerializer = null;
        private RedisSerializer valueSerializer = null;
        private RedisSerializer hashKeySerializer = null;
        private RedisSerializer hashValueSerializer = null;
        private RedisSerializer<String> stringSerializer = new StringRedisSerializer();

    因为spring操作redis是在jedis客户端基础上进行的,而jedis客户端与redis交互的时候协议中定义是用byte类型交互,jedis中提供了string类型转为byte[]类型,但是看到spring-data-redis中RedisTemplate<K, V>在操作的时候k,v是泛型的,所以RedisTemplate中有了上面那段代码,在没有特殊定义的情况下,spring默认采用defaultSerializer = new JdkSerializationRedisSerializer();来对key,value进行序列化操作,在经过查看JdkSerializationRedisSerializer中对序列化的一系列操作,发现如下代码:

    private Converter<Object, byte[]> serializer = new SerializingConverter();
        public byte[] serialize(Object object) {
            if (object == null) {
                return SerializationUtils.EMPTY_ARRAY;
            }
            try {
                return serializer.convert(object);
            } catch (Exception ex) {
                throw new SerializationException("Cannot serialize", ex);
            }
        }

    序列化支持的是Object对象,调用了SerializingConverter类下的convert方法转换对象,转换对象的方法是:

    private final Serializer<Object> serializer;
        /**
         * Serializes the source object and returns the byte array result.
         */
        public byte[] convert(Object source) {
            ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128);
            try  {
                this.serializer.serialize(source, byteStream);
                return byteStream.toByteArray();
            }
            catch (Throwable ex) {
                throw new SerializationFailedException("Failed to serialize object using " +
                        this.serializer.getClass().getSimpleName(), ex);
            }
        }

    原因其实就出现在这里,解决的办法就是手动定义序列化的方法,spring-data-redis中还提供了一个序列化的类专门针对string类型的序列化org.springframework.data.redis.serializer.StringRedisSerializer这个类,可以在xml里面指定:

    @Bean
        public RedisTemplate<String, Serializable> serialRedisTemplate(){
            RedisTemplate<String, Serializable> template = new RedisTemplate<>();
            template.setKeySerializer(new StringRedisSerializer());
            template.setHashKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
            template.setConnectionFactory(palmRedisConnectionFactory());
            return template;
        }

     修改后,的存储结果:

  • 相关阅读:
    [转]回车和换行
    计算机常见缩略词备忘录
    Linux多线程编程阅读链接
    字符串匹配KMP算法
    k8s测试集群部署
    搭建Vmware Harbor 镜像仓库
    GitLab搭建
    Gerrit2安装配置
    linux文件系统问题:wrong fs type, bad option, bad superblock
    Docker容器内不能联网的6种解决方案
  • 原文地址:https://www.cnblogs.com/duanxz/p/12074310.html
Copyright © 2011-2022 走看看