RedisTemplate序列化器的正确定义

       SpringBoot集成Redis后,如果使用redis存储Object,redis默认的序列化器在写入key或value时会以二进制的形式存储,并不方便我们日常观察他的key和value,如下图。因此我们需要自定义序列化器配置来方便我们更好的观察它的key和value,目前比较流行有两种配置方式。

第一种、使用spring-data-redis的jar里的org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer.
 

  @Bean
  public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
    //指定Jackson2JsonRedisSerializer为Object的序列化器,替代redis默认的序列化器JdkSerializationRedisSerializer
    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(factory);

    ObjectMapper objectMapper = new ObjectMapper();
    //反序列化时智能识别变量名(识别没有按驼峰格式命名的变量名)
    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    //反序列化识别对象类型
    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    //反序列化如果有多的属性,不抛出异常
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    //反序列化如果碰到不识别的枚举值,是否作为空值解释,true:不会抛不识别的异常, 会赋空值,false:会抛不识别的异常
    objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);

    jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.afterPropertiesSet();

    return redisTemplate;
  }

    1.1、反序列化时智能识别变量名(识别没有按驼峰格式命名的变量名)。配置代码如下:

    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

反例演示如下:

redis的value值,key没有按驼峰格式命名, 反序列化时出现不识别导致赋值providerOrderNo的值为null。


   1.2、序列化和反序列化识别对象类型。配置代码如下:

    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

 添加这个配置后,存储到redis的对象的字符串我们会出现“@type”字样的标识,并标示时哪一种对象,反序列化时也根据这个标识识别对象的类型。

1.3、反序列化如果有多的属性,不抛出异常。代码配置如下:
 

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

没配置时,从redis缓存中获取字符串值进行反序列化对象时报“org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unrecognized field "appId"”的错误。

反例演示:

redis的value新增一个属性appId。

反序列化成对象时报不识别的属性appId, 如下:

1.4、反序列化如果碰到不识别的枚举值,是否作为空值解释,true:不会抛不识别的异常, 会赋空值,false:会抛不识别的异常。代码配置如下:
 

    objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);

反例演示:

修改redis的value的枚举属性值:

反序列化时,报不识别的枚举值。

第二种:直接使用Fastjson的序列化器(1.2.68以上的版本漏洞已修复)

     注明:fastJson版本<=1.2.68,存在远程代码执行的漏洞。我们项目中如果使用小于或等于1.2.68版本的fastjson,需要及时升级修复漏洞。

@Bean
  public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory, RedisSerializer fastJson2JsonRedisSerializer) {
    RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
    redisTemplate.setConnectionFactory(factory);

    //key采用String序列化方式
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    redisTemplate.setKeySerializer(stringRedisSerializer);
    redisTemplate.setHashKeySerializer(stringRedisSerializer);

    //value采用fast-json序列化方式。
    redisTemplate.setValueSerializer(fastJson2JsonRedisSerializer);
    redisTemplate.setHashValueSerializer(fastJson2JsonRedisSerializer);

    redisTemplate.afterPropertiesSet();
    return redisTemplate;
  }

  @Bean
  public RedisSerializer fastJson2JsonRedisSerializer() {
    return new FastJson2JsonRedisSerializer<>(Object.class);
  }

  public static class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {

    public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

    private Class<T> clazz;

    public FastJson2JsonRedisSerializer(Class<T> clazz) {
      super();
      this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
      if (t == null) {
        return new byte[0];
      }
      return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
      if (bytes == null || bytes.length <= 0) {
        return null;
      }
      String str = new String(bytes, DEFAULT_CHARSET);
      return JSON.parseObject(str, clazz, Feature.SupportAutoType);
    }

  }

 

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值