首頁  >  文章  >  資料庫  >  SpringBoot怎麼自訂Redis實作快取序列化

SpringBoot怎麼自訂Redis實作快取序列化

WBOY
WBOY轉載
2023-06-03 11:32:231040瀏覽

1、自訂RedisTemplate

1.1、Redis API預設序列化機制

基於API的Redis快取實作是使用RedisTemplate模板進行資料快取操作的,這裡開啟RedisTemplate類,查看該類別的原始碼資訊

public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
    // 声明了key、value的各种序列化方式,初始值为空
    @Nullable
    private RedisSerializer keySerializer = null;
    @Nullable
    private RedisSerializer valueSerializer = null;
    @Nullable
    private RedisSerializer hashKeySerializer = null;
    @Nullable
    private RedisSerializer hashValueSerializer = null;
...
    // 进行默认序列化方式设置,设置为JDK序列化方式
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        boolean defaultUsed = false;
        if (this.defaultSerializer == null) {
            this.defaultSerializer = new JdkSerializationRedisSerializer(
                    this.classLoader != null ?
                            this.classLoader : this.getClass().getClassLoader());
        }
        ...
    }
        ...
}

從上述RedisTemplate核心原始碼可以看出,在RedisTemplate內部宣告了快取資料key、value的各種序列化方式,且初始值都為空;在afterPropertiesSet()方法中,判斷如果預設序列化參數defaultSerializer為空,將資料的預設序列化方式設定為JdkSerializationRedisSerializer

根據上述原始碼資訊的分析,可以得到以下兩個重要的結論:

# (1)使用RedisTemplate進行Redis數據緩存操作時,內部默認使用的是JdkSerializationRedisSerializer序列化方式,所以進行數據緩存的實體類必須實現JDK自帶的序列化接口(例如Serializable);

( 2)使用RedisTemplate進行Redis資料快取操作時,如果自訂了快取序列化方式defaultSerializer,那麼就會使用自訂的序列化方式。

另外,在RedisTemplate類別原始碼中,看到的快取資料key、value的各種序列化類型都是RedisSerializer。進入RedisSerializer原始碼查看RedisSerializer支援的序列化方式(進入該類別後,使用Ctrl Alt 左鍵單擊類別名稱查看)

SpringBoot怎麼自訂Redis實作快取序列化

##可以看出,RedisSerializer是一個Redis序列化接口,預設有6個實現類,這6個實現類代表了6種不同的資料序列化方式。其中,JdkSerializationRedisSerializer是JDK自帶的,也是RedisTemplate內部預設使用的資料序列化方式,開發者可以根據需要選擇其他支援的序列化方式(例如JSON方式)

1.2、自訂RedisTemplate序列化機制

在專案中引入Redis相依性後,Spring Boot提供的RedisAutoConfiguration自動設定會生效。開啟RedisAutoConfiguration類,查看內部原始碼中關於RedisTemplate的定義方式

public class RedisAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean(
            name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
...
}

從上述RedisAutoConfiguration核心原始碼中可以看出,在Redis自動配置類別中,透過Redis連接工廠RedisConnectionFactory初始化了一個RedisTemplate;該類別上方新增了@ConditionalOnMissingBean註解(顧名思義,當某個Bean不存在時生效),用來表示如果開發者自訂了一個名為redisTemplate的Bean,則該預設初始化的RedisTemplate不會生效。

如果想要使用自訂序列化方式的RedisTemplate進行資料快取操作,可以參考上述核心程式碼建立一個名為redisTemplate的Bean元件,並在該元件中設定對應的序列化方式即可

接下來,在專案中建立名為com.lagou.config的套件,在該套件下建立一個Redis自訂設定類別RedisConfig,並依照上述思路自訂名為redisTemplate的Bean元件

@Configuration
public class RedisConfig {
    // 自定义RedisTemplate
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 创建一个JSON格式序列化对象,对缓存数据的key和value进行转换
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        // 解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // 设置RedisTemplate模板api序列化方式为json
        template.setDefaultSerializer(jackson2JsonRedisSerializer);
        return template;
    }
}

透過@Configuration註解定義了一個RedisConfig配置類,並使用@Bean註解注入了一個預設名稱為方法名的redisTemplate元件(注意,該Bean元件名稱必須是redisTemplate)。在定義的Bean元件中,自訂了一個RedisTemplate,使用自訂的Jackson2JsonRedisSerializer資料序列化方式;在自訂序列化方式中,定義了一個ObjectMapper用於進行資料轉換設定

#1.3、效果測試

SpringBoot怎麼自訂Redis實作快取序列化

可以看出,執行findById()方法正確查詢出使用者評論資訊Comment,重複進行同樣的查詢操作,資料庫只執行了一次SQL語句,這說明定制的Redis快取生效。

使用Redis用戶端視覺化管理工具Redis Desktop Manager查看快取資料:

SpringBoot怎麼自訂Redis實作快取序列化

執行findById()方法查詢出使用者評論資訊Comment正確儲存到了Redis在快取庫中,且快取到Redis服務的資料已經使用了JSON格式儲存展示,檢視和管理也非常方便,說明自訂的Redis API範本工具RedisTemplate生效

2、自訂RedisCacheManager

剛剛針對基於API方式的RedisTemplate進行了自訂序列化方式的改進,從而實現了JSON序列化方式緩存數據,但是這種自定義的RedisTemplate對於基於註解的Redis緩存來說,是沒有作用的。

接下來,針對基於註解的Redis快取機制和自訂序列化方式進行解說

2.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版本中,RedisCacheManager是独立构建的。因此,在SpringBoot 2.X版本中,对RedisTemplate进行自定义序列化机制构建后,仍然无法对RedisCacheManager内部默认序列化机制进行覆盖(这也就解释了基 于注解的Redis缓存实现仍然会使用JDK默认序列化机制的原因),想要基于注解的Redis缓存实现也使用自定义序列化机制,需要自定义RedisCacheManager

2.2、自定义RedisCacheManager

在项目的Redis配置类RedisConfig中,按照上一步分析的定制方法自定义名为cacheManager的Bean组件

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
        RedisSerializer<String> strSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jacksonSerial = new Jackson2JsonRedisSerializer(Object.class);
        // 解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); // 上面注释过时代码的替代方法
        jacksonSerial.setObjectMapper(om);
        // 定制缓存数据序列化方式及时效
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1)) // 设置缓存数据的时效(设置为了1天)
                .serializeKeysWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(strSerializer)) // 对当前对象的key使用strSerializer这个序列化对象,进行转换
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(jacksonSerial)) // 对value使用jacksonSerial这个序列化对象,进行转换
                .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测试时,实体类可以不用实现序列化接口)

以上是SpringBoot怎麼自訂Redis實作快取序列化的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除