学科分类
目录
Spring Boot开发

自定义RedisCacheManager

在6.4.1小节中,针对基于Redis API的RedisTemplate进行了自定义序列化机制的改进,从而实现了相对熟悉的JSON格式缓存数据,但是这种自定义的RedisTemplate对于基于注解的Redis缓存实现来说,是没有作用的,读者可以自行演示。接下来,针对基于注解的Redis缓存机制和自定义序列化方式的实现进行讲解。

1.Redis注解默认序列化机制

打开Spring Boot整合Redis组件提供的缓存自动配置类RedisCacheConfiguration(org.springframework.boot.autoconfigure.cache包下的),查看该类的源码信息,其核心代码如下。

@Configuration
class RedisCacheConfiguration {
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory
                                    redisConnectionFactory,ResourceLoader resourceLoader) {
        RedisCacheManagerBuilder builder =
                      RedisCacheManager.builder(redisConnectionFactory)
         .cacheDefaults(this.determineConfiguration(resourceLoader.getClassLoader()));
        List<String> cacheNames = this.cacheProperties.getCacheNames();
        if(!cacheNames.isEmpty()) {
            builder.initialCacheNames(new LinkedHashSet(cacheNames));
        }
        return (RedisCacheManager)this.customizerInvoker.customize(builder.build());
    }
    private org.springframework.data.redis.cache.RedisCacheConfiguration
 determineConfiguration(ClassLoader classLoader){
        if(this.redisCacheConfiguration != null) {
            return this.redisCacheConfiguration;
        } else {
            Redis redisProperties = this.cacheProperties.getRedis();
            org.springframework.data.redis.cache.RedisCacheConfiguration config =
    org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig();
            config = config.serializeValuesWith(SerializationPair.fromSerializer(
                                     new JdkSerializationRedisSerializer(classLoader)));
            ...
            return config;
        }
    }
}

从上述核心源码中可以看出,同RedisTemplate核心源码类似,RedisCacheConfiguration内部同样通过Redis连接工厂RedisConnectionFactory定义了一个缓存管理器RedisCacheManager;同时定制RedisCacheManager时,也默认使用了JdkSerializationRedisSerializer序列化方式。

如果想要使用自定义序列化方式的RedisCacheManager进行数据缓存操作,可以参考上述核心代码创建一个名为cacheManager的Bean组件,并在该组件中设置对应的序列化方式即可。

需要注意的是,本书使用的是Spring Boot 2.X版本进行使用讲解,这与Spring Boot 1.X版本中的一些实现原理并不相同。例如上述RedisCacheManager的构建方式,在Spring Boot 1.X版本中的源码如下。

@Bean
public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
    RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
    cacheManager.setUsePrefix(true);
    List<String> cacheNames = this.cacheProperties.getCacheNames();
    if(!cacheNames.isEmpty()) {
        cacheManager.setCacheNames(cacheNames);
    }
    return (RedisCacheManager)this.customizerInvoker.customize(cacheManager);
}

从这两个版本的源码对比可以看出,Spring Boot 1.X版本中,RedisCacheManager是在RedisTemplate的基础上述进行构建的,而Spring Boot 2.X版本中,RedisCacheManager是单独进行构建的。因此,在Spring Boot 2.X版本中,对RedisTemplate进行自定义序列化机制构建后,仍然无法对RedisCacheManager内部默认序列化机制进行覆盖(这也就解释了基于注解的Redis缓存实现仍然会使用JDK默认序列化机制的原因),想要基于注解的Redis缓存实现也使用自定义序列化机制,需要自定义RedisCacheManager。

2.自定义RedisCacheManager

在chapter06项目的Redis配置类RedisConfig中,按照上一步分析的定制方法自定义名为cacheManager的Bean组件,示例代码如下:

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    // 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
    RedisSerializer<String> strSerializer = new StringRedisSerializer();
    Jackson2JsonRedisSerializer jacksonSeial = 
new Jackson2JsonRedisSerializer(Object.class);
    // 解决查询缓存转换异常的问题
    ObjectMapper om = new ObjectMapper();
    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jacksonSeial.setObjectMapper(om);
    // 定制缓存数据序列化方式及时效
    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofDays(1))
             .serializeKeysWith(RedisSerializationContext.SerializationPair
                                  .fromSerializer(strSerializer))                      
            .serializeValuesWith(RedisSerializationContext.SerializationPair
                                  .fromSerializer(jacksonSeial))
            .disableCachingNullValues();
    RedisCacheManager cacheManager = RedisCacheManager
                    .builder(redisConnectionFactory).cacheDefaults(config).build();
    return cacheManager;
}

上述代码中,在RedisConfig配置类中使用@Bean注解注入了一个默认名称为方法名的cacheManager组件。在定义的Bean组件中,通过RedisCacheConfiguration对缓存数据的key和value分别进行了序列化方式的定制,其中缓存数据的key定制为StringRedisSerializer(即String格式),而value定制为了Jackson2JsonRedisSerializer(即JSON格式),同时还使用entryTtl(Duration.ofDays(1))方法将缓存数据有效期设置为1天。

完成基于注解的Redis缓存管理器RedisCacheManager定制后,可以对该缓存管理器的效果进行测试(使用自定义序列化机制的RedisCacheManager测试时,实体类可以不用实现序列化接口),具体的测试方法与效果与6.4.1小节中的测试方法和效果一样,读者可以自行演示。

点击此处
隐藏目录