springboot整合spring-data-redis中的坑

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

##描述 使用springboot整合redis,使用默认的序列化配置,然后使用redis-client去查询时查询不到相应的key.

使用工具发现,key的前面多了\xAC\xED\x00\x05t\x00!这样一个串.

图1

而且value也是不能直观可见的.

##问题所在 使用springdataredis,默认情况下是使用org.springframework.data.redis.serializer.JdkSerializationRedisSerializer这个类来做序列化.

org.springframework.data.redis.core.RedisTemplate代码块.


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

解决

手动设置key的序列化方式为StringRedisSerializer,强制使用.

**由于spring不支持泛型注入,这样会导致所有的redisTemplate的key序列方式都为StringRedisSerializer. ** _同时,最好在序列化对象保存时候手动将其转为json串后存入redis.易于在可视化工具中直接查看对应value _


    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(factory);
        RedisSerializer stringRedisSerializer = new StringRedisSerializer();//Long类型不可以会出现异常信息;
        redisTemplate.setKeySerializer(stringRedisSerializer);
        return redisTemplate;
    }

其他的解决方案

使用GenericJackson2JsonRedisSerializer


redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

这样Object类型的value数据也能在redis json可视化.

自定义自己的序列化

由于使用的是fastjson作为web的序列方式,想统一.于是自己实现了一个

public class FastJson2JsonRedisSerializer implements RedisSerializer {

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Class clazz;

    static {
        ParserConfig.getGlobalInstance().addAccept("这里是允许反序列的白名单包名");
    }
    public FastJson2JsonRedisSerializer() {
    }

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

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

    public T deserialize(byte[] bytes) {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }

        String str = new String(bytes, DEFAULT_CHARSET);
        if(clazz==null){
            return (T) JSON.parse(str);
        }
        return (T) JSON.parseObject(str, clazz);
    }

}

注意

fastjson 的AutoType功能是存在重大漏洞的,在1.2.25后才修复.具体:

https://github.com/alibaba/fastjson/wiki/enable_autotype

转载于:https://my.oschina.net/superwen/blog/885879

你可能感兴趣的:(springboot整合spring-data-redis中的坑)