SpringBoot2.0 version custom Redis serialization

Inscription

Follow the video of Station B to learn how to suddenly encounter version problems. In SpringBoot1.0 version, the custom Redis serialization operation is particularly simple. New a custom RedisTemplate is fine, but in SpringBoot2.0 version, since Defining the serialization of Redis becomes a little more complicated.

Problems:

The default serializer used is JdkSerializationRedisSerializer. This serializer leads to the result shown in the figure below, so we need to customize serialization.
Insert picture description here

Custom serialization process:

1. First look at the implementation of default serialization

The implementation process is in org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration (automatic configuration component)

@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());
	}

In fact, the focus of this method lies in the following code:

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

Analysis:
In this code, the code structure is to use the builder mode to create a builder object, and then we need to use this builder object to build the RedisCacheManager object we need to implement serialization. The main objects involved in generating the creator are CacheProperties and RedisCacheConfiguration. Among these two objects, cacheProperties loads the cache configuration in the configuration file, which has nothing to do with custom implementation of serialization. The key is the RedisCacheConfiguration object.
See how this class comment is written

/**
 * 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
 */

A brief translation, RedisCacheConfiguration helps to customize behaviors, such as cache value, cache key prefix and binary serialization. The task now is to figure out the serialization process of RedisCacheConfiguration. There are two member variables in the RedisCacheConfiguration class:

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

This looks to know that it is used to achieve serialization, where the type of keySerializationPair is String, and the type of valueSerializationPair is Object, which explains why the key is displayed normally when stored in redis, and the value is incomprehensible after translation. Sequence bytecode. So we need to customize the serialization of values. There is a serializeValuesWith method in the RedisCacheConfiguration class, which implements the process of serializing values.

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

There is a static code block in the SerializationPair object, which uses the adapter pattern to provide an interface for our custom serializer. We can implement custom serialization as long as we pass in the custom serializer.

	/**
    * 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. Custom serialization

1. Implement custom 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. Implement a custom RedisCacheManager:
    @Bean
    public RedisCacheManager myCacheManager(RedisConnectionFactory redisConnectionFactory) {
    
    
    	//把前面自定义好的myRedisCacheConfiguration作为参数传入,最后使用创建者模式返回RedisCacheManager对象,实现自定义序列化
        RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder
        .fromConnectionFactory(redisConnectionFactory).cacheDefaults(myRedisCacheConfiguration());
        RedisCacheManager cm = builder.build();
        return cm;
    }

Guess you like

Origin blog.csdn.net/TreeCode/article/details/108309430