Maison  >  Article  >  base de données  >  Comment SpringBoot personnalise Redis pour implémenter la sérialisation du cache

Comment SpringBoot personnalise Redis pour implémenter la sérialisation du cache

WBOY
WBOYavant
2023-06-03 11:32:231090parcourir

1. RedisTemplate personnalisé

1.1, mécanisme de sérialisation par défaut de l'API Redis

L'implémentation du cache Redis basée sur l'API utilise le modèle RedisTemplate pour les opérations de mise en cache des données. Ouvrez la classe RedisTemplate ici pour afficher les informations sur le code source de cette classe

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

Depuis. ci-dessus Il ressort du code source principal de RedisTemplate que diverses méthodes de sérialisation pour la clé et la valeur des données mises en cache sont déclarées dans RedisTemplate et que les valeurs initiales sont toutes vides dans la méthode afterPropertiesSet() ; Le paramètre de sérialisation par défaut defaultSerializer est vide, les données La méthode de sérialisation par défaut est définie sur JdkSerializationRedisSerializer

Sur la base de l'analyse des informations de code source ci-dessus, les deux conclusions importantes suivantes peuvent être tirées :

(1) Lors de l'utilisation de RedisTemplate pour exécuter Redis opérations de mise en cache des données, la méthode de sérialisation interne par défaut est JdkSerializationRedisSerializer. Par conséquent, la classe d'entité pour la mise en cache des données doit implémenter la propre interface de sérialisation du JDK (telle que Serialisable) (2) Lors de l'utilisation de RedisTemplate pour effectuer des opérations de mise en cache de données Redis ; méthode de sérialisation du cache defaultSerializer est personnalisé, puis celui personnalisé sera utilisé comme méthode de sérialisation.

De plus, dans le code source de la classe RedisTemplate, les différents types de sérialisation des clés et valeurs de données mises en cache vues sont RedisSerializer. Entrez le code source de RedisSerializer pour afficher les méthodes de sérialisation prises en charge par RedisSerializer (après être entré dans la classe, utilisez Ctrl+Alt+clic gauche sur le nom de la classe pour afficher)

Comment SpringBoot personnalise Redis pour implémenter la sérialisation du cacheOn peut voir que RedisSerializer est une interface de sérialisation Redis, avec 6 implémentations par classe par défaut, ces 6 classes d'implémentation représentent 6 méthodes de sérialisation de données différentes. Parmi eux, JdkSerializationRedisSerializer est fourni avec JDK et est également la méthode de sérialisation des données par défaut utilisée dans RedisTemplate. Les développeurs peuvent choisir d'autres méthodes de sérialisation prises en charge (telles que la méthode JSON) en fonction de leurs besoins

1.2. La dépendance Redis est introduite dans le projet, la configuration automatique RedisAutoConfiguration fournie par Spring Boot prendra effet. Ouvrez la classe RedisAutoConfiguration et vérifiez la définition de RedisTemplate dans le code source interne

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

Comme le montre le code source principal de RedisAutoConfiguration mentionné ci-dessus, dans la classe de configuration automatique Redis, un RedisTemplate est initialisé via la fabrique de connexion Redis RedisConnectionFactory ; @ConditionalOnMissingBean est ajouté au-dessus de la classe Annotation (comme son nom l'indique, prend effet lorsqu'un certain Bean n'existe pas), utilisée pour indiquer que si le développeur personnalise un Bean nommé redisTemplate, le RedisTemplate initialisé par défaut ne prendra pas effet.

Si vous souhaitez utiliser RedisTemplate avec une méthode de sérialisation personnalisée pour les opérations de mise en cache des données, vous pouvez vous référer au code principal ci-dessus pour créer un composant Bean nommé redisTemplate et définir la méthode de sérialisation correspondante dans le composant

Ensuite, créez un package nommé com.lagou.config dans le projet, créez une classe de configuration personnalisée Redis RedisConfig sous le package et personnalisez le composant Bean nommé redisTemplate selon les idées ci-dessus

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

Définissez un RedisConfig via l'annotation @Configuration Configurez la classe et utilisez le @ Annotation Bean pour injecter un composant redisTemplate avec le nom par défaut du nom de la méthode (notez que le nom du composant Bean doit être redisTemplate). Dans le composant Bean défini, un RedisTemplate est personnalisé, à l'aide de la méthode de sérialisation des données Jackson2JsonRedisSerializer personnalisée ; dans la méthode de sérialisation personnalisée, un ObjectMapper est défini pour les paramètres de conversion des données

1.3, les tests d'effet

On peut voir que le informations sur les commentaires de l'utilisateur Le commentaire est correctement interrogé en exécutant la méthode findById(). Si la même opération de requête est répétée, la base de données n'exécute l'instruction SQL qu'une seule fois, ce qui montre que le cache Redis personnalisé prend effet.

Comment SpringBoot personnalise Redis pour implémenter la sérialisation du cacheUtilisez l'outil de gestion visuelle du client Redis Redis Desktop Manager pour afficher les données mises en cache :

Exécutez la méthode findById() pour interroger les informations du commentaire de l'utilisateur. Le commentaire est correctement stocké dans la bibliothèque de cache Redis et les données mises en cache dans. le service Redis a été utilisé. L'affichage, la visualisation et la gestion du stockage au format JSON sont également très pratiques, ce qui indique que l'outil de modèle d'API Redis personnalisé RedisTemplate est efficace

Comment SpringBoot personnalise Redis pour implémenter la sérialisation du cache2. RedisCacheManager personnalisé

vient d'améliorer la méthode de sérialisation personnalisée pour l'API. basé sur RedisTemplate pour réaliser la méthode de sérialisation JSON est utilisé pour mettre en cache les données, mais ce RedisTemplate personnalisé n'a aucun effet sur la mise en cache Redis basée sur les annotations.

Ensuite, nous expliquerons le mécanisme de mise en cache Redis basé sur les annotations et la méthode de sérialisation personnalisée

2.1, mécanisme de sérialisation par défaut des annotations Redis

Ouvrez la classe de configuration automatique du cache RedisCacheConfiguration (paquet org.springframework. boot.autoconfigure.cache), vue les informations sur le code source de cette classe, son code principal est le suivant

@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测试时,实体类可以不用实现序列化接口)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer