Java使用Redis 的序列化问题

197 阅读1分钟

redis序列化

配置了 redisConfig

@Configuration
public class RedisConfig extends CachingConfigurerSupport  {
    @Resource(type = RedisConnectionFactory.class)
    private RedisConnectionFactory redisConnectionFactory;

    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate() {

        //创建一个RedisTemplate对象,为了方便返回key为string,value为Object
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        // 配置连接工厂
        template.setConnectionFactory(redisConnectionFactory);

        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        // 解决反序列化 LocalDateTime 的错误
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

        // 解决 LocalDateTime 序列化失败的问题
        objectMapper.registerModule(new JavaTimeModule());

        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

        objectMapper.activateDefaultTyping(
                LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL,
                JsonTypeInfo.As.WRAPPER_ARRAY);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        //使用StringRedisSerializer序列化和反序列化redis的key值
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);

        // value采用jackson的序列化方式
        template.setValueSerializer(jackson2JsonRedisSerializer);

        //hash的value也采用jackson的序列化方式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);

        template.afterPropertiesSet();

        return template;
    }
}

在使用redisTemplate发现,有时候走的是自己配置的序列化规则,有时候又是默认的转成String类型的规则。

1.png

2.png 通过观察发现: 两个注入RedisTemplate的方式不同

使用@Autowired 注入,通过类型找然后找泛型对应上的最后通过名称,导致注入的是StringRedisTermplate 得到一个String对象

使用@Resource 注入,先使用名称找,就能找到自己配置的config,序列化反序列化规则。

但是对于自己配序列化规则,数字类型长度小的时候是Integer, 大于Integer的范围就是Long类型,需要使用Object接收,序列化,在反序列化使用 new TypeReference,

 String amountJson = JSONObject.toJSONString(opsForHash.get(RedisKeyConstants.TODAY_REQUEST_BUY_AMOUNT + requestBuyId, dateStr));
        if (StringUtils.isNotBlank(amountJson) && !"null".equals(amountJson)) {
            amount = JSONObject.parseObject(amountJson, new TypeReference<>() {
            });
        }

3.png

4.png