ホームページ  >  記事  >  データベース  >  SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法

SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法

WBOY
WBOY転載
2023-06-03 11:32:231090ブラウズ

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内で宣言されており、初期値は空です。 afterPropertiesSet() メソッド、デフォルトのシリアル化パラメーターdefaultSerializer が空かどうかを確認、データのデフォルトのシリアル化メソッドを JdkSerializationRedisSerializer に設定します

上記のソース コード情報の分析によれば、次の 2 つの重要な結論を引き出すことができます。 :

(1) Redis データ キャッシュ操作に RedisTemplate を使用する場合、内部のデフォルトのシリアル化メソッドは JdkSerializationRedisSerializer であるため、データ キャッシュ用のエンティティ クラスは JDK 独自のシリアル化インターフェイス (Serializable など) を実装する必要があります。

( 2) RedisTemplate を使用して Redis データ キャッシュ操作を実行する場合、キャッシュのシリアル化メソッド defaultSerializer がカスタマイズされている場合は、カスタマイズされたシリアル化メソッドが使用されます。

さらに、RedisTemplate クラスのソース コードでは、キャッシュされたデータのキーと値のさまざまなシリアル化タイプが RedisSerializer として表示されます。 RedisSerializer のソース コードを入力して、RedisSerializer でサポートされているシリアル化メソッドを表示します (クラスを入力した後、Ctrl Alt を使用してクラス名を左クリックして表示します)。 RedisSerializer が Redis であることがわかりました。シリアル化インターフェイスにはデフォルトで 6 つの実装クラスがあり、これら 6 つの実装クラスは 6 つの異なるデータ シリアル化メソッドを表します。その中で、JdkSerializationRedisSerializer は JDK に付属しており、RedisTemplate 内で使用されるデフォルトのデータシリアル化メソッドでもあり、開発者は必要に応じて、サポートされている他のシリアル化メソッド (JSON メソッドなど) を選択できます。

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 自動構成クラスでは、RedisTemplate が Redis 接続ファクトリを通じて初期化されます。 RedisConnectionFactory; クラスの上 @ConditionalOnMissingBean アノテーション (名前が示すように、Bean が存在しない場合に有効になります) は、開発者が redisTemplate という名前の Bean をカスタマイズする場合、デフォルトで初期化された RedisTemplate が有効にならないことを示すために追加されます。 SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法

データ キャッシュ操作のカスタム シリアル化メソッドで 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;
    }
}

は RedisConfig を定義します@Configuration アノテーションを通じて構成クラスを取得し、@Bean アノテーションを使用してメソッド名のデフォルト名を持つ redisTemplate コンポーネントを注入します (Bean コンポーネント名は redisTemplate である必要があることに注意してください)。定義された Bean コンポーネントでは、カスタマイズされた Jackson2JsonRedisSerializer データシリアル化メソッドを使用して RedisTemplate がカスタマイズされます。カスタマイズされたシリアル化メソッドでは、データ変換設定用に ObjectMapper が定義されます

1.3、効果テスト

#findById() メソッドを実行すると、ユーザー コメント情報 Comment が正しくクエリされ、同じクエリ操作が繰り返されることがわかります。データベースは SQL ステートメントを 1 回だけ実行します。これは、カスタマイズが Redis によって行われたことを示しています。キャッシュが有効になります。

Redis クライアントのビジュアル管理ツール Redis Desktop Manager を使用して、キャッシュされたデータを表示します。

findById() メソッドを実行して、ユーザーのコメント情報をクエリし、コメントは Redis に正しく保存されています。キャッシュ ライブラリには、Redis サービスにキャッシュされたデータが JSON 形式で保存および表示されており、カスタマイズされた Redis API テンプレート ツール RedisTemplate が有効であることを示す表示と管理も非常に便利です。 SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法

2. カスタマイズされた RedisCacheManager

API ベースの RedisTemplate のカスタム シリアル化メソッドを改良し、データをキャッシュするための JSON シリアル化メソッドを実現しましたが、このカスタム RedisTemplate は、アノテーションベースの Redis キャッシュ。

次に、アノテーションベースの Redis キャッシュメカニズムとカスタムシリアル化メソッドについて説明します

SpringBoot が Redis をカスタマイズしてキャッシュのシリアル化を実装する方法2.1. Redis アノテーションのデフォルトのシリアル化メカニズム

Open 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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。