SpringBoot2.0版本自定义Redis序列化

题记

跟着B站的视频学着学着突然遇到版本问题,在SpringBoot1.0版本中,自定义Redis序列化操作特别简单,new一个自定义的RedisTemplate就好了,但是在SpringBoot2.0版本中,自定义Redis的序列化就变得稍微复杂一点。

出现的问题:

默认使用的序列器是JdkSerializationRedisSerializer,此序列化器导致下图结果,所以我们需要自定义序列化。
在这里插入图片描述

自定义序列化过程:

1. 先看默认序列化的实现

实现过程在org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration(自动配置组件)中

@Bean
	RedisCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers,
			ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration,
			ObjectProvider<RedisCacheManagerBuilderCustomizer> redisCacheManagerBuilderCustomizers,
			RedisConnectionFactory redisConnectionFactory, ResourceLoader resourceLoader) {
    
    
		RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(
				determineConfiguration(cacheProperties, redisCacheConfiguration, resourceLoader.getClassLoader()));
		List<String> cacheNames = cacheProperties.getCacheNames();
		if (!cacheNames.isEmpty()) {
    
    
			builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
		}
		redisCacheManagerBuilderCustomizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
		return cacheManagerCustomizers.customize(builder.build());
	}

其实这个方法的重点就在下面这句代码中:

	RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(
			determineConfiguration(cacheProperties, redisCacheConfiguration, resourceLoader.getClassLoader()));

分析:
在这句代码中,代码结构就是使用建造者模式,创建出一个builder对象,之后需要用这个builder对象建造我们需要用于实现序列化的RedisCacheManager对象。生成创建者时涉及到的主要对象有CacheProperties ,RedisCacheConfiguration。而这两个对象中,cacheProperties是加载配置文件中的缓存配置的,与自定义实现序列化没啥关系,关键是RedisCacheConfiguration这个对象。
看看这个类注释怎么写的

/**
 * Immutable {@link RedisCacheConfiguration} helps customizing {@link RedisCache} behaviour such as caching
 * {@literal null} values, cache key prefixes and binary serialization. <br />
 * Start with {@link RedisCacheConfiguration#defaultCacheConfig()} and customize {@link RedisCache} behaviour from there
 * on.
 *
 * @author Christoph Strobl
 * @author Mark Paluch
 * @since 2.0
 */

简单翻译一下,RedisCacheConfiguration帮助自定义行为,如缓存值,缓存键前缀和二进制序列化。现在的任务就是搞清楚RedisCacheConfiguration实现序列化的过程,在RedisCacheConfiguration类中有两个成员变量:

	private final SerializationPair<String> keySerializationPair;
	private final SerializationPair<Object> valueSerializationPair;

这一看知道是用来实现序列化的,其中keySerializationPair的类型是String,valueSerializationPair的类型是Object,这就解释了为什么存入redis时,key是正常显示,而value是看不懂的转译后的序列字节码。所以我们需要自定义值的序列化。在类RedisCacheConfiguration中有一个serializeValuesWith方法,这个方法就实现了值序列化的过程。

	public RedisCacheConfiguration serializeValuesWith(SerializationPair<?> valueSerializationPair) {
    
    

		Assert.notNull(valueSerializationPair, "ValueSerializationPair must not be null!");
		//返回一个RedisCacheConfiguration对象,其中的valueSerializationPair是由参数传入的SerializationPair对象
		return new RedisCacheConfiguration(ttl, cacheNullValues, usePrefix, keyPrefix, keySerializationPair,
				valueSerializationPair, conversionService);
	}

在SerializationPair对象中有一个静态代码块,使用了适配器模式,提供了我们自定义序列化器的接口,我们只要把自定义的序列化器传进去就可以实现自定义序列化了。

	/**
    * Creates a {@link SerializationPair} adapter given {@link RedisSerializer}.
	*
	* @param serializer must not be {@literal null}.
	* @return a {@link SerializationPair} adapter for {@link RedisSerializer}.
	*/
    static <T> SerializationPair<T> fromSerializer(RedisSerializer<T> serializer) {
    
    

		Assert.notNull(serializer, "RedisSerializer must not be null!");

		return new RedisSerializerToSerializationPairAdapter<>(serializer);
	}

2.自定义序列化

1.实现自定义RedisCacheConfiguration:
@Bean
public RedisCacheConfiguration myRedisCacheConfiguration() {
    
    
    //使用json序列化器
    RedisSerializer<Object> jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
    //将选用的自定义序列化器传入SerializationPair.fromSerializer这个静态代码块中,从而得到一个SerializationPair
    RedisSerializationContext.SerializationPair<Object> serializationPair = RedisSerializationContext.SerializationPair
            .fromSerializer(jackson2JsonRedisSerializer);
	//将SerializationPair用于存入Redis中值的序列化
    return RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(serializationPair);
}
2. 实现自定义RedisCacheManager:
    @Bean
    public RedisCacheManager myCacheManager(RedisConnectionFactory redisConnectionFactory) {
    
    
    	//把前面自定义好的myRedisCacheConfiguration作为参数传入,最后使用创建者模式返回RedisCacheManager对象,实现自定义序列化
        RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder
        .fromConnectionFactory(redisConnectionFactory).cacheDefaults(myRedisCacheConfiguration());
        RedisCacheManager cm = builder.build();
        return cm;
    }

猜你喜欢

转载自blog.csdn.net/TreeCode/article/details/108309430