关于springboot集成redis及关于redis的Key 乱码问题

其实这里的"乱码"并不是真的乱码,那是因为我们还缺少了一点配置,那就是对Redis存key或者value的时候,没有配置字符串序列化。没有配置的话是默认使用jdk本身的序列化的,点进去RedisTemplate里面去看,可以看到
 

关于springboot集成redis及关于redis的Key 乱码问题_第1张图片

 关于springboot集成redis及关于redis的Key 乱码问题_第2张图片

 

因为spring操作redis是在jedis客户端基础上进行的,而jedis客户端与redis交互的时候协议中定义是用byte类型交互,看到spring-data-redis中RedisTemplate在操作的时候k,v是泛型对象,而不是byte[]类型的,这样导致的一个问题就是,如果不对RedisTemplate进行设置,spring会默认采用defaultSerializer = new JdkSerializationRedisSerializer();这个方法来对key、value进行序列化操作,JdkSerializationRedisSerializer它使用的编码是ISO-8859-1。

 

Reids提供了很多RedisSerializer的实现类:

关于springboot集成redis及关于redis的Key 乱码问题_第3张图片

但是都不好有,我们使用阿里爸爸提供的fastJson。


    com.alibaba
    fastjson
    1.2.47

关于springboot集成redis及关于redis的Key 乱码问题_第4张图片

 利用springboot的自动装配,先将这些东西配置好,这些配置在网上可以找到,springboot集成redis配置


@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    
    @Bean
    public RedisTemplate redisTemplate(
            RedisConnectionFactory redisConnectionFactory)
            throws UnknownHostException {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);

        RedisSerializer serializer = new FastJsonRedisSerializer(Object.class);
        template.setKeySerializer(serializer);
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(serializer);
        template.setHashValueSerializer(serializer);

        return template;
    }
}

关于springboot集成redis及关于redis的Key 乱码问题_第5张图片

 

 改进版:

虽然成功的将数据以json方式存放到redis中,但是在读取json后确不知道要反序列列话成什么对象。

 @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

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


        FastJsonRedisSerializer jsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        jsonRedisSerializer.getFastJsonConfig().setSerializerFeatures(SerializerFeature.WriteClassName);
        ParserConfig.getGlobalInstance().addAccept("com.hsc.www.");

        template.setValueSerializer(jsonRedisSerializer); //设置value采用的fastjson的序列化方式
        template.setHashValueSerializer(jsonRedisSerializer);//设置hash的value采用的fastjson的序列化方式
        template.setDefaultSerializer(jsonRedisSerializer);//设置其他默认的序列化方式为fastjson

        template.afterPropertiesSet();
        return template;
    }

json: 

{
    "@type": "com.hsc.www.amqp.util.RabbitMetaMessage",
    "bizName": "testBus",
    "exchange": "123456",
    "messageId": "612f4bec-09c2-4934-b9f5-3dd92e26ee25",
    "payload": {
        "@type": "com.hsc.www.amqp.config.User",
        "id": 1561604289080,
        "name": "0f423408-5e84-4a88-889b-7ae5f2f8d57a"
    },
    "prepareSendTime": 1561604289088,
    "routingKey": "1"
}

这种json加了@type属性。

2017年3月15日,fastjson官方发布安全升级公告,该公告介绍fastjson在1.2.24及之前的版本存在代码执行漏洞,当恶意攻击者提交一个精心构造的序列化数据到服务端时,由于fastjson在反序列化时存在漏洞,可导致远程任意代码执行。 
自1.2.25及之后的版本,禁用了部分autotype的功能,也就是”@type”这种指定类型的功能会被限制在一定范围内使用。 
而由于反序列化对象时,需要检查是否开启了autotype。所以如果反序列化检查时,autotype没有开启,就会报错。
阿里提供的解决方法:https://github.com/alibaba/fastjson/wiki/enable_autotype

你可能感兴趣的:(SpringBoot)