[Série SpringBoot] Solution de cache

Présentation de la mise en cache

Le rôle principal des applications au niveau de l'entreprise est le traitement de l'information. Lorsque des données doivent être lues, les performances globales du système sont faibles en raison de l'efficacité d'accès limitée de la base de données.

insérez la description de l'image ici

L'application traite directement avec la base de données et l'efficacité de l'accès est faible

Afin d'améliorer le phénomène ci-dessus, les développeurs établissent généralement un mécanisme de stockage de données temporaire entre l'application et la base de données. Les données de cette zone sont stockées dans la mémoire et la vitesse de lecture et d'écriture est rapide, ce qui peut résoudre efficacement le problème. de la faible efficacité d'accès à la base de données. Cette zone de stockage temporaire des données est le cache .

insérez la description de l'image ici

Après avoir utilisé le cache, l'application traite le cache, le cache traite la base de données et l'efficacité de l'accès aux données est améliorée

缓存C'est un support entre le support de stockage permanent des données et l'applicationsupport de stockage temporaire de données

  • L'utilisation d'un cache peut réduire efficacement le nombre de processus de lecture de données à faible vitesse (tels que les E/S de disque) et améliorer les performances du système.
  • Le cache peut non seulement être utilisé pour améliorer l'efficacité de lecture des données des supports de stockage permanents, mais également fournir un espace de stockage de données temporaire.

Parfois, nous pouvons même créer des caches à plusieurs niveaux :
insérez la description de l'image ici

Springboot fournit une solution pour intégrer presque toutes les technologies de mise en cache sur le marché.Commençons ensemble le voyage de l'intégration de Springboot en cache.

Solution de mise en cache intégrée SpringBoot

La technologie springboot fournit une solution de mise en cache intégrée, qui peut aider les développeurs à activer rapidement la technologie de mise en cache et à utiliser la technologie de mise en cache pour effectuer des opérations de données rapides, telles que la lecture de données en cache et l'écriture de données dans le cache .

Etape 1 : Importer le starter correspondant à la technologie de cache fournie par springboot

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

Étape 2 : Activez la mise en cache, annotez @EnableCaching au-dessus de la classe de démarrage pour configurer le programme springboot pour utiliser la mise en cache

@SpringBootApplication
//开启缓存功能
@EnableCaching
public class Springboot19CacheApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Springboot19CacheApplication.class, args);
    }
}

Étape ③ : Définir s'il faut utiliser le cache pour les données de l'opération

@Service
public class BookServiceImpl implements BookService {
    
    
    @Autowired
    private BookDao bookDao;

    @Cacheable(value="cacheSpace",key="#id")
    public Book getById(Integer id) {
    
    
        return bookDao.selectById(id);
    }
}

Sur la méthode métier, utilisez l'annotation @Cacheable pour déclarer que la valeur de retour de la méthode courante est mise en cache, ce qui précise l'emplacement de stockage du cache et le nom correspondant à la valeur de retour de la méthode courante stockée dans le cache . Dans l'exemple ci-dessus, l'attribut value décrit l'emplacement de stockage du cache, qui peut être compris comme un nom d'espace de stockage. L'attribut key décrit le nom des données stockées dans le cache. Utilisez #id pour lire la valeur id dans le paramètre formel comme nom de cache .

Après avoir utilisé l'annotation @Cacheable, effectuez l'opération en cours. S'il s'avère que le nom correspondant n'a pas de données dans le cache, il lira les données normalement, puis les mettra dans le cache ; si le nom correspondant a des données dans le cache, il mettra fin à l'exécution de la méthode métier en cours et retournera directement au cache.

Nous envoyons des requêtes plusieurs fois dans PostMan :
insérez la description de l'image ici
dans nos journaux, nous pouvons voir que la première fois que la base de données est manipulée, puis les données sont extraites du cache :
insérez la description de l'image ici

En plus de fournir la solution de mise en cache par défaut, la technologie de mise en cache fournie par SpringBoot peut également intégrer d'autres technologies de mise en cache et unifier l'interface pour faciliter le développement et la gestion des technologies de mise en cache :

  • Générique
  • JCache
  • Ehcache
  • Noisette
  • Infinispan
  • Base de canapé
  • Redis
  • Caféine
  • Simple (par défaut)
  • memcached

SpringBoot intègre la mise en cache Ehcache

Commençons par springboot pour intégrer diverses technologies de mise en cache, la première à intégrer la technologie Ehcache. Ehcache est une technologie de mise en cache. Utiliser springboot pour intégrer Ehcache revient en fait à changer l'implémentation de la technologie de mise en cache. Pas grand chose à dire, il suffit d'ouvrir le tout

Etape 1 : Importer les coordonnées d'Ehcache

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

​ Pourquoi ne pas importer ici le starter d'Ehcache, mais importer les coordonnées techniques ? En fait, springboot intègre la technologie de mise en cache dans un format général. Peu importe la technologie de mise en cache que vous intégrez, l'implémentation a changé et la méthode de fonctionnement est la même . Cela reflète également les avantages de la technologie springboot et unifie la méthode d'intégration de technologies similaires.

Étape 2 : Configurer la technologie de cache pour utiliser Ehcache

spring:
  cache:
    type: ehcache
    ehcache:
      config: ehcache.xml

Le type de cache de configuration est ehcache.Il faut expliquer ici que la technologie de mise en cache actuelle que springboot peut intégrer inclut ehcach, donc il peut être écrit comme ceci. En fait, ce type ne peut pas être écrit par hasard, et il ne peut pas être intégré en écrivant simplement un nom.

La configuration de ehcache ayant un format de fichier de configuration indépendant, il est également nécessaire de spécifier le fichier de configuration de ehcache pour faciliter la lecture de la configuration correspondante

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <diskStore path="D:\ehcache" />

    <!--默认缓存策略 -->
    <!-- external:是否永久存在,设置为true则不会被清除,此时与timeout冲突,通常设置为false-->
    <!-- diskPersistent:是否启用磁盘持久化-->
    <!-- maxElementsInMemory:最大缓存数量-->
    <!-- overflowToDisk:超过最大缓存数量是否持久化到磁盘-->
    <!-- timeToIdleSeconds:最大不活动间隔,设置过长缓存容易溢出,设置过短无效果,可用于记录时效性数据,例如验证码-->
    <!-- timeToLiveSeconds:最大存活时间-->
    <!-- memoryStoreEvictionPolicy:缓存清除策略-->
    <defaultCache
        eternal="false"
        diskPersistent="false"
        maxElementsInMemory="1000"
        overflowToDisk="false"
        timeToIdleSeconds="60"
        timeToLiveSeconds="60"
        memoryStoreEvictionPolicy="LRU" />

    <cache
        name="smsCode"
        eternal="false"
        diskPersistent="false"
        maxElementsInMemory="1000"
        overflowToDisk="false"
        timeToIdleSeconds="10"
        timeToLiveSeconds="10"
        memoryStoreEvictionPolicy="LRU" />
</ehcache>

Notez que dans le cas du code de vérification du téléphone mobile, l'emplacement où les données sont enregistrées est smsCode

@CachePut(value = "smsCode", key = "#tele")
public String sendCodeToSMS(String tele) {
    
    
    String code = codeUtils.generator(tele);
    return code;
}	

Ce paramètre doit garantir qu'il existe une configuration avec un nom d'espace de cache appelé smsCode dans ehcache, qui doit être unifié avant et après.Dans le processus de développement de l'entreprise, différentes stratégies de mise en cache sont définies en définissant des caches avec des noms différents (attributs de nom), qui sont appliqués à différentes données mises en cache.

À ce stade, springboot a terminé l'intégration d'Ehcache. On peut constater que le code d'origine n'a pas été modifié et que le fournisseur de cache ne peut être changé qu'en ajoutant un ensemble de configurations. C'est également l'avantage que springboot fournit un unifié interface d'opération de cache N'affecte pas l'écriture du code d'origine.

Résumer

  1. springboot utilise Ehcache comme cache pour implémenter les coordonnées qui doivent être importées dans Ehcache
  2. Modifiez les paramètres, configurez le fournisseur de cache en tant que ehcache et fournissez le fichier de configuration de cache correspondant

SpringBoot intègre le cache Redis

Comparez le processus d'utilisation d'Ehcache, ajoutez des coordonnées, changez le type d'implémentation du cache en ehcache et configurez Ehcache. Et si redis est toujours utilisé pour la mise en cache ? Exactement la même chose, ajoutez des coordonnées, changez le type d'implémentation du cache en redis et configurez redis.La seule différence est que la configuration de redis peut être configurée directement dans le fichier yml sans créer de fichier de configuration séparé.

Etape 1 : Importer les coordonnées de redis

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Étape 2 : Configurer la technologie de cache pour utiliser redis

spring:
  redis:
    host: localhost
    port: 6379
  cache:
    type: redis

N'oubliez pas que lors de l'utilisation de la technologie de mise en cache redis, le serveur doit être activé

Si vous avez besoin de configurer redis en cache, faites attention à ne pas configurer le redis d'origine, mais à configurer redis en cache pour utiliser la configuration pertinente, qui appartient au nœud spring.cache.redis, veillez à ne pas écrire le mauvais endroit.

spring:
  redis:
    host: localhost
    port: 6379
  cache:
    type: redis
    redis:
      use-key-prefix: false
      key-prefix: sms_
      cache-null-values: false
      time-to-live: 10s

Annotation des paramètres :

  • time-to-live définit la durée de vie du cache
  • use-key-prefix n'utilise pas le préfixe de la clé. Nous pouvons voir que lorsqu'il est défini sur true, le smsCode précédent a disparu. Dans ce cas, le risque est très élevé et les données peuvent être répétées.
    insérez la description de l'image ici
  • key-prefix : spécifie le préfixe. On voit key-prefix: sms_l'effet :
    insérez la description de l'image ici
  • Si on utilise key-prefixavec use-key-prefix:
    insérez la description de l'image ici
    insérez la description de l'image ici
  • cache-null-values : s'il faut mettre en cache les valeurs nulles

Résumer

  1. springboot utilise redis comme cache pour implémenter les coordonnées qui doivent être importées dans redis
  2. Modifiez les paramètres, configurez le fournisseur de cache en tant que redis et fournissez la configuration de cache correspondante

SpringBoot intègre la mise en cache Memcached

À l'heure actuelle, nous maîtrisons les formes de configuration de trois solutions de mise en cache, à savoir le cache intégré springboot, ehcache et redis.Dans cette section, nous étudierons un cache domestique populaire, memcached.

Selon la routine précédente, il n'est pas fastidieux de modifier le cache, mais springboot ne supporte pas l'utilisation de memcached comme solution de cache, c'est-à-dire qu'il n'y a pas d'option de configuration pour memcached dans l'attribut type, donc la méthode de traitement doit être changé ici. Installez memcached avant l'intégration.

Installer

Adresse de téléchargement du package d'installation de la version Windows : https://www.runoob.com/memcached/window-install-memcached.html

​ Le package d'installation téléchargé est un fichier zip qui peut être utilisé après décompression. Après décompression, les fichiers suivants seront obtenus

insérez la description de l'image ici

​ Le fichier exécutable ne contient qu'un seul memcached.exe, qui peut être utilisé pour démarrer memcached en tant que service système. Un message d'erreur apparaîtra lors de l'exécution de ce fichier, comme suit :

insérez la description de l'image ici

La raison du problème ici est que vous devez utiliser les privilèges d'administrateur lors de l'enregistrement des services système. Le compte actuel a des privilèges insuffisants et l'installation du service échoue. Changez les privilèges du compte administrateur pour démarrer la ligne de commande.

insérez la description de l'image ici

​ Ensuite, exécutez la commande pour réinstaller le service, comme suit :

memcached.exe -d install

Une fois le service installé, vous pouvez utiliser les commandes pour démarrer et arrêter le service, comme suit :

memcached.exe -d start		# 启动服务
memcached.exe -d stop		# 停止服务

​ Vous pouvez également changer l'état du service dans le gestionnaire de tâches

insérez la description de l'image ici

Changer le cache en Memcached

Étant donné que memcached n'est pas inclus en tant que solution de mise en cache par springboot, l'utilisation de memcached doit être utilisée par codage manuel, de sorte que les routines précédentes ne s'appliquent pas et vous devez l'écrire vous-même.

​ Memcached fournit actuellement trois technologies client, à savoir Memcached Client for Java, SpyMemcached et Xmemcached.Parmi elles, le client avec les meilleurs indicateurs de performance est Xmemcached, qui est utilisé comme technologie d'implémentation client pour cette intégration. Commençons à utiliser Xmemcached

Sélection de la technologie clientinsérez la description de l'image ici

Etape 1 : Importer les coordonnées de xmemcached

<dependency>
    <groupId>com.googlecode.xmemcached</groupId>
    <artifactId>xmemcached</artifactId>
    <version>2.4.7</version>
</dependency>

Étape 2 : Configurer memcached et créer une classe de configuration pour memcached

Étant donné que SpringBoot n'intègre pas memcached, il ne peut pas être configuré dans le fichier de configuration. Vous ne pouvez écrire manuellement que des classes de configuration

@Configuration
public class XMemcachedConfig {
    
    
    @Bean
    public MemcachedClient getMemcachedClient() throws IOException {
    
    
        MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder("localhost:11211");
        MemcachedClient memcachedClient = memcachedClientBuilder.build();
        return memcachedClient;
    }
}

L'adresse du serveur et le port de memcached sont écrits dans XMemcachedClientBuilder.

​ memcached utilise par défaut le port de service externe 11211.

Etape 3 : Utiliser le client xmemcached pour faire fonctionner le cache et injecter l'objet MemcachedClient

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    
    
    @Autowired
    private CodeUtils codeUtils;
    @Autowired
    private MemcachedClient memcachedClient;

    public String sendCodeToSMS(String tele) {
    
    
        String code = codeUtils.generator(tele);
        try {
    
    
            memcachedClient.set(tele,10,code);
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
    
    
        String code = null;
        try {
    
    
            code = memcachedClient.get(smsCode.getTele()).toString();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return smsCode.getCode().equals(code);
    }
}

La méthode memcachedClient.set() lève une exception, où :
le premier paramètre : spécifie la clé mise en cache
Le second paramètre : spécifie le délai d'expiration. 0 signifie qu'il n'expire jamais, 10 signifie que 10s est valide
Le troisième paramètre : la valeur mise en cache spécifiée La
méthode memcachedClient.get() lèvera également une exception

​ Pour définir la valeur dans le cache, utilisez l'opération set, et utilisez l'opération get pour récupérer la valeur, ce qui est en fait plus conforme aux habitudes de nos développeurs.

Dans le code ci-dessus, la configuration du serveur est codée en dur dans le code, et ces données sont extraites et transformées en un attribut de configuration indépendant.

Définir les propriétés de configuration

Le processus suivant adopte la méthode de configuration de propriété

  • Définissez la classe de configuration, chargez les propriétés de configuration nécessaires et lisez les informations du nœud memcached dans le fichier de configuration

    @Component
    @ConfigurationProperties(prefix = "memcached")
    @Data
    public class XMemcachedProperties {
          
          
        private String servers;
        private int poolSize;
        private long opTimeout;
    }
    
  • Définir les informations du nœud memcached

    memcached:
      servers: localhost:11211
      poolSize: 10
      opTimeout: 3000
    
  • Charger les informations dans la classe de configuration memcached

@Configuration
public class XMemcachedConfig {
    
    
    @Autowired
    private XMemcachedProperties props;
    @Bean
    public MemcachedClient getMemcachedClient() throws IOException {
    
    
        MemcachedClientBuilder memcachedClientBuilder = new XMemcachedClientBuilder(props.getServers());
        memcachedClientBuilder.setConnectionPoolSize(props.getPoolSize());
        memcachedClientBuilder.setOpTimeout(props.getOpTimeout());
        MemcachedClient memcachedClient = memcachedClientBuilder.build();
        return memcachedClient;
    }
}

Résumer

  1. Après l'installation de memcached, le service correspondant doit être démarré avant de pouvoir fournir la fonction de cache externe. L'installation du service memcached doit être basée sur les privilèges d'administrateur système Windows.
  2. Étant donné que springboot ne fournit pas de solution d'intégration de cache pour memcached, il est nécessaire de créer le cache d'opération client xmemcached sous la forme d'un codage manuel
  3. Après avoir importé les coordonnées xmemcached, créez une classe de configuration memcached et enregistrez le bean correspondant à MemcachedClient pour faire fonctionner le cache
  4. Les propriétés nécessaires pour initialiser l'objet MemcachedClient peuvent être chargées sous la forme d'une classe de propriétés de configuration personnalisée

SpringBoot intègre la mise en cache jetcache

Actuellement, les caches que nous utilisons sont A ou B. A et B peuvent-ils être utilisés ensemble ? L'intégration des caches par Springboot ne reste que sur l'utilisation des caches. Si le cache lui-même ne prend pas en charge l'utilisation d'AB en même temps, springboot ne peut pas le faire. Par conséquent, afin de résoudre le problème de l'utilisation conjointe des caches AB, vous doit trouver un cache qui peut prendre en charge à la fois AB et AB. Le cache est utilisé ensemble, existe-t-il un tel cache ? Il y a vraiment, produit Ali, jetcache.

La solution d'Ali résout nos deux problèmes d'origine :
① Les solutions de cache d'origine que nous avons utilisées étaient configurées en yml, configurées en xml et contrôlées dans la classe de configuration. C'est très compliqué et désordonné.②
Lorsque nous faisons le schéma de mise en cache, nous utilisons soit la forme locale, telle que ehcache, simple (par défaut), et nous ne configurons pas l'adresse IP et le port lorsque nous les utilisons. Soit utiliser une solution distante, telle que redis, memcached, lorsque nous les utilisons, nous configurons l'adresse IP et le port. Il existe des plans locaux. Il n'y a pas de schéma à distance, mais seulement la neutralisation des deux schémas. Nous n'avons besoin que de la neutralisation des deux car la solution à distance impliquera inévitablement des problèmes de réseau et sa vitesse sera lente, mais elle résout le problème du cache partagé entre plusieurs serveurs. Et on résout le problème de la vitesse avec le local, mais pas le problème du partage.

Jetcache n'est pas à proprement parler une solution de cache, on peut seulement dire que c'est un framework de cache, et puis d'autres caches sont gérés dans jetcache, de sorte que les caches AB peuvent être utilisés ensemble . Et jetcache fait référence à l'idée de springboot d'intégrer la mise en cache, et l'utilisation globale de la technologie est très similaire à l'idée de solution de mise en cache de springboot. Utilisons d'abord jetcache, puis parlons de quelques petites fonctions qu'il contient.

Avant de le faire, précisez que jetcache ne peut pas simplement prendre deux caches ensemble. Actuellement, jetcache prend en charge deux types de schémas de mise en cache : la mise en cache locale et la mise en cache distante, qui sont les suivantes :

  • Cache local (Local)
    • LinkedHashMap
    • Caféine
  • Cache distant (distant)
    • Redis
    • Trois

Solution à distance pure

Etape 1 : Importez springboot pour intégrer le démarreur de coordonnées correspondant à jetcache. Le schéma distant par défaut utilisé par la coordonnée actuelle est redis

<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.2</version>
</dependency>

Étape 2 : Configuration de base du schéma distant

jetcache:
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50

maxTotal indique le nombre maximum de connexions

Le poolConfig est un élément obligatoire, sinon une erreur sera signalée

Étape 3 : Activez la mise en cache, marquez l'annotation @EnableCreateCacheAnnotation au-dessus de la classe de démarrage pour configurer le programme springboot afin de créer un cache sous forme d'annotations

@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
public class Springboot20JetCacheApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Springboot20JetCacheApplication.class, args);
    }
}

Étape 4 : Créez l'objet cache Cache et utilisez l'annotation @CreateCache pour marquer les informations du cache actuel, puis utilisez l'API de l'objet Cache pour faire fonctionner le cache, mettre le cache en écriture et obtenir le cache en lecture.

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    
    
    @Autowired
    private CodeUtils codeUtils;
    
    @CreateCache(name="jetCache_",expire = 10,timeUnit = TimeUnit.SECONDS)
    private Cache<String ,String> jetCache;

    public String sendCodeToSMS(String tele) {
    
    
        String code = codeUtils.generator(tele);
        jetCache.put(tele,code);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
    
    
        String code = jetCache.get(smsCode.getTele());
        return smsCode.getCode().equals(code);
    }
}
private Cache<String ,String> jetCache;

Il s'agit de créer un objet cache, qui peut être compris comme définissant un hashmap, bien sûr, il existe d'autres paramètres

@CreateCache(name="jetCache_",expire = 10,timeUnit = TimeUnit.SECONDS)

Cette phrase équivaut à dire à jetcache qu'il s'agit d'un objet cache.

  • name est l'espace de noms, équivalent à la valeur dans Ehcache
  • expire est la durée du cache, l'unité par défaut est la seconde
  • timeUnit est utilisé pour définir l'unité de temps du cache. Vous pouvez utiliser cet élément de configuration lorsque vous ne souhaitez pas utiliser l'unité par défaut.

Grâce au jetcache mentionné ci-dessus utilisant le schéma distant pour se connecter à redis, on peut voir que le fonctionnement de l'interface lorsque jetcache exploite le cache est plus conforme aux habitudes du développeur.Lors de l'utilisation du cache, l'objet cache Cache est obtenu en premier, les données sont insérées et les données sont extraites, ce qui est plus simple et facile à comprendre. . Et lorsque jetcache exploite le cache, vous pouvez définir le délai d'expiration d'un objet de cache, et mettre le même type de données dans le cache pour faciliter la gestion de la période effective .

Le schéma ci-dessus utilise le cache par défaut défini dans la configuration,En fait, cette valeur par défaut est un nom, vous pouvez l'écrire avec désinvolture ou l'ajouter avec désinvolture.. Par exemple, pour ajouter une autre solution de mise en cache, reportez-vous à la configuration suivante :

jetcache:
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50
    sms:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50

​ Si vous souhaitez utiliser le cache avec le nom sms, vous devez spécifier le paramètre area lors de la création du cache, et déclarer le cache correspondant.

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    
    
    @Autowired
    private CodeUtils codeUtils;
    
    @CreateCache(area="sms",name="jetCache_",expire = 10,timeUnit = TimeUnit.SECONDS)
    private Cache<String ,String> jetCache;

    public String sendCodeToSMS(String tele) {
    
    
        String code = codeUtils.generator(tele);
        jetCache.put(tele,code);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
    
    
        String code = jetCache.get(smsCode.getTele());
        return smsCode.getCode().equals(code);
    }
}

solution locale pure

Dans le schéma distant, remote est utilisé dans la configuration pour indiquer distant, et local est local, mais le type est différent.

Etape 1 : Importer springboot pour intégrer le starter de coordonnées correspondant à jetcache

<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.2</version>
</dependency>

Étape 2 : configuration de base du cache local

jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson

Afin d'accélérer la vitesse de correspondance des clés lors de l'acquisition des données, jetcache nécessite un convertisseur de type pour spécifier la clé. En termes simples, si vous donnez un objet comme clé, je le convertis d'abord en chaîne à l'aide du convertisseur de type de clé, puis je l'enregistre. Lorsque les données sont obtenues, l'objet donné est toujours d'abord converti en chaîne, puis mis en correspondance en fonction de la chaîne. Étant donné que jetcache est la technologie d'Ali, il est recommandé d'utiliser le fastjson d'Ali comme convertisseur de type de clé ici.

Étape ③ : Activer la mise en cache

@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
public class Springboot20JetCacheApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Springboot20JetCacheApplication.class, args);
    }
}

Étape 4 : Lors de la création de l'objet cache Cache, marquez l'utilisation actuelle du cache local

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    
    
    @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.LOCAL)
    private Cache<String ,String> jetCache;

    public String sendCodeToSMS(String tele) {
    
    
        String code = codeUtils.generator(tele);
        jetCache.put(tele,code);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
    
    
        String code = jetCache.get(smsCode.getTele());
        return smsCode.getCode().equals(code);
    }
}

cacheType contrôle si le cache actuel utilise le cache local ou le cache distant. Configurez cacheType=CacheType.LOCAL pour utiliser le cache local.

Scénario local + distant

Des méthodes locales et distantes sont disponibles. Comment configurer les deux schémas ensemble ? En fait, il suffit de combiner les deux configurations.

jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50
    sms:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50

Lors de la création d'un cache, configurez cacheType sur BOTH, c'est-à-dire que le cache local et le cache distant sont utilisés en même temps.

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    
    
    @CreateCache(name="jetCache_",expire = 1000,timeUnit = TimeUnit.SECONDS,cacheType = CacheType.BOTH)
    private Cache<String ,String> jetCache;
}

Si cacheType n'est pas configuré, la valeur par défaut est REMOTE, c'est-à-dire que seul le schéma de cache distant est utilisé. Pour la configuration du jetcache, reportez-vous aux informations suivantes

Les attributs Valeurs par défaut illustrer
jetcache.statIntervalMinutes 0 Intervalle de statistiques, 0 signifie pas de statistiques
jetcache.hiddenPackages rien Lorsque le nom est généré automatiquement, masquez le préfixe du nom de package spécifié
jetcache.[local|distant].${zone}.type rien Type de cache, support local linkedhashmap, caféine, redis de support à distance, tair
jetcache.[local|distant].${zone}.keyConvertor rien convertisseur de clé, ne prend actuellement en charge que fastjson
jetcache.[local|distant].${zone}.valueEncoder Java Seul le cache de type distant doit être spécifié, java et kryo facultatifs
jetcache.[local|distant].${zone}.valueDecoder Java Seul le cache de type distant doit être spécifié, java et kryo facultatifs
jetcache.[local|distant].${zone}.limit 100 Seul le type de cache local doit être spécifié, le nombre maximum d'éléments de l'instance de cache
jetcache.[local|distant].${zone}.expireAfterWriteInMillis Sans précédent Délai d'expiration par défaut, en millisecondes
jetcache.local.${area}.expireAfterAccessInMillis 0 Seuls les caches de type local sont valides, millisecondes, intervalle d'inactivité maximum

Les solutions ci-dessus ne prennent en charge que le contrôle manuel du cache, mais le cache de méthode dans la solution springcache est particulièrement utile. Ajoutez une annotation à une méthode et la méthode utilisera automatiquement le cache. Jetcache fournit également une fonction correspondante, à savoir la mise en cache des méthodes.

cache de méthodes

​ jetcache fournit une solution de mise en cache des méthodes, mais le nom a changé. Utilisez simplement l'annotation @Cached au-dessus de l'interface d'opération correspondante

Etape 1 : Importer springboot pour intégrer le starter de coordonnées correspondant à jetcache

<dependency>
    <groupId>com.alicp.jetcache</groupId>
    <artifactId>jetcache-starter-redis</artifactId>
    <version>2.6.2</version>
</dependency>

Etape 2 : Configurer le cache

jetcache:
  local:
    default:
      type: linkedhashmap
      keyConvertor: fastjson
  remote:
    default:
      type: redis
      host: localhost
      port: 6379
      keyConvertor: fastjson
      valueEncode: java
      valueDecode: java
      poolConfig:
        maxTotal: 50
    sms:
      type: redis
      host: localhost
      port: 6379
      poolConfig:
        maxTotal: 50

Étant donné que le cache Redis ne prend pas en charge l'enregistrement d'objets, il est nécessaire de définir comment effectuer la conversion de type pour Redis lorsque les données de type d'objet entrent dans Redis. Le keyConvertor doit être configuré pour indiquer la méthode de conversion de type de la clé, et en même temps, la méthode de type de conversion de la valeur doit être marquée. Lorsque la valeur entre dans redis, elle est de type java et le valueEncode est marqué comme java.

Notez que pour implémenter la valeur de type d'objet dans et hors de redis, il est nécessaire de s'assurer que les données de type objet dans et hors de redis doivent implémenter l'interface de sérialisation.

@Data
public class Book implements Serializable {
    
    
    private Integer id;
    private String type;
    private String name;
    private String description;
}

Étape ③ : Activez la fonction de cache de méthode lorsque le cache est activé,Et configurez basePackages pour indiquer dans quels packages la mise en cache des méthodes est activée

@SpringBootApplication
//jetcache启用缓存的主开关
@EnableCreateCacheAnnotation
//开启方法注解缓存
@EnableMethodCache(basePackages = "com.nefu")
public class Springboot20JetCacheApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Springboot20JetCacheApplication.class, args);
    }
}

Étape 4 : Utilisez l'annotation @Cached pour marquer la méthode actuelle pour utiliser le cache

@Service
public class BookServiceImpl implements BookService {
    
    
    @Autowired
    private BookDao bookDao;
    
    @Override
    @Cached(name="book",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
    public Book getById(Integer id) {
    
    
        return bookDao.selectById(id);
    }
}

résultat:
insérez la description de l'image ici

Synchronisation des données pour les scénarios distants

Étant donné que les données enregistrées par redis dans le schéma distant peuvent être partagées par plusieurs clients, il existe un problème de synchronisation des données. Jetcache fournit 3 annotations pour résoudre ce problème, en synchronisant les données mises en cache lors des opérations de mise à jour et de suppression, et en actualisant périodiquement les données lors de la lecture du cache

actualiser le cache

@CacheUpdate(name="book_",key="#book.id",value="#book")
public boolean update(Book book) {
    
    
    return bookDao.updateById(book) > 0;
}

supprimer le cache

@CacheInvalidate(name="book_",key = "#id")
public boolean delete(Integer id) {
    
    
    return bookDao.deleteById(id) > 0;
}

Actualiser périodiquement le cache

En pensant aux scénarios d'utilisation : s'il existe une table, le système A peut maintenant modifier cette table, et le système B peut également modifier cette table. Or le système A a lu les données de cette table dans le cache, et en même temps, le système B a modifié les données de cette table. Cela ne provoque-t-il pas une erreur (les données en mémoire et les données de la table ne sont pas synchronisées) ? Le système A ne sait pas que la table a changé à ce moment et utilise toujours les anciennes données dans le cache. Pour le dire franchement, le système B ne dira pas au système A que la table a changé après avoir utilisé la table.

Nous pouvons utiliser @CacheRefresh pour rafraîchir le cache (les données dans le cache à ce moment) régulièrement, l'unité par défaut est la seconde

@Cached(name="book_",key="#id",expire = 3600,cacheType = CacheType.REMOTE)
@CacheRefresh(refresh = 5)
public Book getById(Integer id) {
    
    
    return bookDao.selectById(id);
}

Si vous constatez que chaque fois que vous accédez à la base de données au lieu du cache, vous pouvez déterminer si la durée du cache est trop courte.

rapport de données

jetcache fournit également une fonction de rapport de données simple pour aider les développeurs à afficher rapidement les informations sur les accès au cache, il suffit d'ajouter une configuration

jetcache:
  statIntervalMinutes: 1

​ Après le réglage, les données de cache de sortie frappent les informations sur la console toutes les 1 minute (unité par défaut)

[DefaultExecutor] c.alicp.jetcache.support.StatInfoLogger  : jetcache stat from 2022-02-28 09:32:15,892 to 2022-02-28 09:33:00,003
cache    |    qps|   rate|   get|    hit|   fail|   expire|   avgLoadTime|   maxLoadTime
---------+-------+-------+------+-------+-------+---------+--------------+--------------
book_    |   0.66| 75.86%|    29|     22|      0|        0|          28.0|           188
---------+-------+-------+------+-------+-------+---------+--------------+--------------

Résumer

  1. Jetcache est une solution de mise en cache similaire à Springcache. Il n'a pas de fonction de mise en cache. Il fournit une solution de mise en cache à plusieurs niveaux qui utilise la mise en cache locale et la mise en cache distante.
  2. Les solutions de mise en cache fournies par jetcache sont limitées par les solutions actuellement prises en charge. Il existe deux types de caches locaux et deux types de caches distants.
  3. Faites attention au problème de conversion de type lorsque les données entrent dans le cache distant
  4. jetcache fournit la mise en cache des méthodes et fournit les fonctions de mise à jour et d'actualisation du cache correspondantes
  5. Jetcache fournit un simple rapport d'accès aux informations de cache pour aider les développeurs à surveiller les accès aux données de cache en temps réel

SpringBoot intègre la mise en cache j2cache

j2cache est un cadre d'intégration de cache, qui peut fournir une solution d'intégration de cache, de sorte que divers caches puissent être utilisés ensemble, et il ne fournit pas de fonction de cache en soi.

Jetcache peut créer des caches à plusieurs niveaux dans une plage limitée, mais il n'est pas assez flexible pour faire correspondre les caches à volonté. Cette section présente un framework d'intégration de cache, j2cache, qui peut être utilisé avec des solutions de mise en cache à volonté. Expliquons comment utiliser ce framework de mise en cache, en prenant l'intégration d'Ehcache et de redis comme exemple :

Etape 1 : Importer les coordonnées j2cache, redis, ehcache

<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-core</artifactId>
    <version>2.8.4-release</version>
</dependency>
<dependency>
    <groupId>net.oschina.j2cache</groupId>
    <artifactId>j2cache-spring-boot2-starter</artifactId>
    <version>2.8.0-release</version>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>

Le démarreur de j2cache contient par défaut les coordonnées redis. Il est officiellement recommandé d'utiliser redis comme cache secondaire, il n'est donc pas nécessaire d'importer les coordonnées redis ici.

Étape 2 : Configurez les caches de premier niveau et de second niveau, et configurez la méthode de transfert de données entre les caches de premier niveau et de second niveau. La configuration est écrite dans un fichier nommé j2cache.properties. Si vous utilisez ehcache, vous devez également ajouter le fichier de configuration ehcache séparément

# 1级缓存
j2cache.L1.provider_class = ehcache
ehcache.configXml = ehcache.xml

# 2级缓存
j2cache.L2.provider_class = net.oschina.j2cache.cache.support.redis.SpringRedisProvider
j2cache.L2.config_section = redis
redis.hosts = localhost:6379

# 1级缓存中的数据如何到达二级缓存
j2cache.broadcast = net.oschina.j2cache.cache.support.redis.SpringRedisPubSubPolicy

La configuration ici ne peut pas être configurée arbitrairement, et vous devez vous référer aux instructions de configuration officielles. Par exemple, si un fournisseur de niveau 1 choisit ehcache, le nom du fournisseur n'est qu'un ehcache, mais lorsqu'un fournisseur de niveau 2 choisit redis, il doit écrire un nom de classe de fournisseur Redis intégré à Spring dédié SpringRedisProvider, et ce nom n'est pas disponible dans tous les packages redis. , également non fournis dans le package de printemps. Par conséquent, pour configurer j2cache, vous devez vous référer au document de configuration officiel, et vous devez également trouver un package d'intégration dédié et importer les coordonnées correspondantes avant de pouvoir l'utiliser.

La configuration la plus importante des caches de premier niveau et de second niveau est la méthode de communication de données entre les deux. Ce type de configuration n'est pas configuré arbitrairement et les méthodes de communication de données fournies par différentes solutions de mise en cache sont très différentes. Vous devez interroger le site officiel document à définir.

Étape ③ : Utiliser le cache

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    
    
    @Autowired
    private CodeUtils codeUtils;

    @Autowired
    private CacheChannel cacheChannel;

    public String sendCodeToSMS(String tele) {
    
    
        String code = codeUtils.generator(tele);
        cacheChannel.set("sms",tele,code);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
    
    
        String code = cacheChannel.get("sms",smsCode.getTele()).asString();
        return smsCode.getCode().equals(code);
    }
}

L'utilisation de j2cache est similaire à jetcache, mais vous n'avez pas besoin d'ouvrir le commutateur pour l'utiliser, il suffit de définir l'objet de cache et de l'utiliser, le nom de l'objet de cache est CacheChannel.

L'utilisation de j2cache n'est pas compliquée, et la configuration est au cœur de j2cache.Après tout, c'est un cadre de mise en cache intégré. Il y a trop de configurations liées au cache. Vous pouvez vous référer à la description dans le fichier j2cache.properties du package principal j2cache-core. comme suit:

#J2Cache configuration
#########################################
# Cache Broadcast Method
# values:
# jgroups -> use jgroups's multicast
# redis -> use redis publish/subscribe mechanism (using jedis)
# lettuce -> use redis publish/subscribe mechanism (using lettuce, Recommend)
# rabbitmq -> use RabbitMQ publisher/consumer mechanism
# rocketmq -> use RocketMQ publisher/consumer mechanism
# none -> don't notify the other nodes in cluster
# xx.xxxx.xxxx.Xxxxx your own cache broadcast policy classname that implement net.oschina.j2cache.cluster.ClusterPolicy
#########################################
j2cache.broadcast = redis

# jgroups properties
jgroups.channel.name = j2cache
jgroups.configXml = /network.xml

# RabbitMQ properties
rabbitmq.exchange = j2cache
rabbitmq.host = localhost
rabbitmq.port = 5672
rabbitmq.username = guest
rabbitmq.password = guest

# RocketMQ properties
rocketmq.name = j2cache
rocketmq.topic = j2cache
# use ; to split multi hosts
rocketmq.hosts = 127.0.0.1:9876

#########################################
# Level 1&2 provider
# values:
# none -> disable this level cache
# ehcache -> use ehcache2 as level 1 cache
# ehcache3 -> use ehcache3 as level 1 cache
# caffeine -> use caffeine as level 1 cache(only in memory)
# redis -> use redis as level 2 cache (using jedis)
# lettuce -> use redis as level 2 cache (using lettuce)
# readonly-redis -> use redis as level 2 cache ,but never write data to it. if use this provider, you must uncomment `j2cache.L2.config_section` to make the redis configurations available.
# memcached -> use memcached as level 2 cache (xmemcached),
# [classname] -> use custom provider
#########################################

j2cache.L1.provider_class = caffeine
j2cache.L2.provider_class = redis

# When L2 provider isn't `redis`, using `L2.config_section = redis` to read redis configurations
# j2cache.L2.config_section = redis

# Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true)
# NOTICE: redis hash mode (redis.storage = hash) do not support this feature)
j2cache.sync_ttl_to_redis = true

# Whether to cache null objects by default (default false)
j2cache.default_cache_null_object = true

#########################################
# Cache Serialization Provider
# values:
# fst -> using fast-serialization (recommend)
# kryo -> using kryo serialization
# json -> using fst's json serialization (testing)
# fastjson -> using fastjson serialization (embed non-static class not support)
# java -> java standard
# fse -> using fse serialization
# [classname implements Serializer]
#########################################

j2cache.serialization = json
#json.map.person = net.oschina.j2cache.demo.Person

#########################################
# Ehcache configuration
#########################################

# ehcache.configXml = /ehcache.xml

# ehcache3.configXml = /ehcache3.xml
# ehcache3.defaultHeapSize = 1000

#########################################
# Caffeine configuration
# caffeine.region.[name] = size, xxxx[s|m|h|d]
#
#########################################
caffeine.properties = /caffeine.properties

#########################################
# Redis connection configuration
#########################################

#########################################
# Redis Cluster Mode
#
# single -> single redis server
# sentinel -> master-slaves servers
# cluster -> cluster servers (数据库配置无效,使用 database = 0)
# sharded -> sharded servers  (密码、数据库必须在 hosts 中指定,且连接池配置无效 ; redis://user:[email protected]:6379/0)
#
#########################################

redis.mode = single

#redis storage mode (generic|hash)
redis.storage = generic

## redis pub/sub channel name
redis.channel = j2cache
## redis pub/sub server (using redis.hosts when empty)
redis.channel.host =

#cluster name just for sharded
redis.cluster_name = j2cache

## redis cache namespace optional, default[empty]
redis.namespace =

## redis command scan parameter count, default[1000]
#redis.scanCount = 1000

## connection
# Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379

redis.hosts = 127.0.0.1:6379
redis.timeout = 2000
redis.password =
redis.database = 0
redis.ssl = false

## redis pool properties
redis.maxTotal = 100
redis.maxIdle = 10
redis.maxWaitMillis = 5000
redis.minEvictableIdleTimeMillis = 60000
redis.minIdle = 1
redis.numTestsPerEvictionRun = 10
redis.lifo = false
redis.softMinEvictableIdleTimeMillis = 10
redis.testOnBorrow = true
redis.testOnReturn = false
redis.testWhileIdle = true
redis.timeBetweenEvictionRunsMillis = 300000
redis.blockWhenExhausted = false
redis.jmxEnabled = false

#########################################
# Lettuce scheme
#
# redis -> single redis server
# rediss -> single redis server with ssl
# redis-sentinel -> redis sentinel
# redis-cluster -> cluster servers
#
#########################################

#########################################
# Lettuce Mode
#
# single -> single redis server
# sentinel -> master-slaves servers
# cluster -> cluster servers (数据库配置无效,使用 database = 0)
# sharded -> sharded servers  (密码、数据库必须在 hosts 中指定,且连接池配置无效 ; redis://user:[email protected]:6379/0)
#
#########################################

## redis command scan parameter count, default[1000]
#lettuce.scanCount = 1000
lettuce.mode = single
lettuce.namespace =
lettuce.storage = hash
lettuce.channel = j2cache
lettuce.scheme = redis
lettuce.hosts = 127.0.0.1:6379
lettuce.password =
lettuce.database = 0
lettuce.sentinelMasterId =
lettuce.maxTotal = 100
lettuce.maxIdle = 10
lettuce.minIdle = 10
# timeout in milliseconds
lettuce.timeout = 10000
# redis cluster topology refresh interval in milliseconds
lettuce.clusterTopologyRefresh = 3000

#########################################
# memcached server configurations
# refer to https://gitee.com/mirrors/XMemcached
#########################################

memcached.servers = 127.0.0.1:11211
memcached.username =
memcached.password =
memcached.connectionPoolSize = 10
memcached.connectTimeout = 1000
memcached.failureMode = false
memcached.healSessionInterval = 1000
memcached.maxQueuedNoReplyOperations = 100
memcached.opTimeout = 100
memcached.sanitizeKeys = false

Résumer

  1. j2cache est un framework de mise en cache qui n'a pas de fonction de mise en cache en soi. Il fournit des solutions pour intégrer plusieurs caches.
  2. j2cache doit configurer tous les niveaux de cache via une configuration complexe, ainsi que le mode d'échange de données entre les caches
  3. L'interface d'opération j2cache est implémentée via CacheChannel

Pièce jointe : Cas du code de vérification du téléphone portable

Ce cas utilise la solution de mise en cache intégrée de SpringBoot

Afin de faciliter la démonstration des différentes technologies de mise en cache ci-dessous, nous créons un environnement de cas pour les codes de vérification mobiles afin de simuler le processus d'utilisation du cache pour enregistrer les codes de vérification mobiles.

Les exigences relatives au cas de code de vérification mobile sont les suivantes :

  • Entrez le numéro de téléphone mobile pour obtenir le code de vérification, et envoyez le document d'organisation à l'utilisateur sous forme de SMS (simulation de page)
  • Entrez le numéro de téléphone portable et le code de vérification pour vérifier le résultat

Afin de décrire les opérations ci-dessus, nous réalisons deux interfaces de couche de présentation, l'une est utilisée pour simuler le processus d'envoi de messages SMS, en fait, un code de vérification est généré en fonction du numéro de téléphone mobile fourni par l'utilisateur, puis stocké dans le cache, et l'autre est utilisé pour simuler la vérification du code de vérification. Le processus consiste en fait à utiliser le numéro de téléphone mobile entrant et le code de vérification pour correspondre, et à renvoyer le résultat final correspondant. Le code de simulation de ce cas est directement produit ci-dessous, et la technologie de mise en cache intégrée fournie par springboot dans l'exemple ci-dessus est utilisée pour terminer la production du cas actuel.

Etape 1 : Importer le starter correspondant à la technologie de cache fournie par springboot

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

Étape 2 : Activez la mise en cache, annotez @EnableCaching au-dessus de la classe de démarrage pour configurer le programme springboot pour utiliser la mise en cache

@SpringBootApplication
//开启缓存功能
@EnableCaching
public class Springboot19CacheApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(Springboot19CacheApplication.class, args);
    }
}

Etape 3 : Définir la classe d'entité correspondant au code de vérification, et encapsuler les deux attributs du numéro de téléphone mobile et du code de vérification

@Data
public class SMSCode {
    
    
    private String tele;
    private String code;
}

Étape 4 : Définir l'interface de la couche métier et la classe d'implémentation de la fonction de code de vérification

public interface SMSCodeService {
    
    
    public String sendCodeToSMS(String tele);
    public boolean checkCode(SMSCode smsCode);
}

@Service
public class SMSCodeServiceImpl implements SMSCodeService {
    
    
    @Autowired
    private CodeUtils codeUtils;

    @CachePut(value = "smsCode", key = "#tele")
    public String sendCodeToSMS(String tele) {
    
    
        String code = codeUtils.generator(tele);
        return code;
    }

    public boolean checkCode(SMSCode smsCode) {
    
    
        //取出内存中的验证码与传递过来的验证码比对,如果相同,返回true
        String code = smsCode.getCode();
        String cacheCode = codeUtils.get(smsCode.getTele());
        return code.equals(cacheCode);
    }
}

Après avoir obtenu le code de vérification, le code de vérification doit être obtenu à nouveau lorsque le code de vérification est invalide. Par conséquent, l'annotation @Cacheable ne peut pas être utilisée dans la fonction d'obtention du code de vérification.L'annotation @Cacheable consiste à mettre une valeur s'il n'y a pas de valeur dans le cache, et à prendre une valeur s'il y a une valeur dans le cache. La fonction ici est uniquement de générer le code de vérification et de le mettre dans le cache, et il n'a pas la fonction d'obtenir la valeur du cache, donc l'annotation @Cacheable ne peut pas être utilisée, et la fonction qui enregistre uniquement les données dans le le cache doit être utilisé et l'annotation @CachePut peut être utilisée. .

Quelques notes supplémentaires ici :

  • Si nous voulons obtenir la valeur du cache, nous pouvons définir une méthode distincte (c'est-à-dire la méthode get dans le code ci-dessus), l'annoter avec @Cacheable et laisser la méthode renvoyer null. La valeur ainsi extraite sera affectée à la valeur de retour de la méthode

  • Pourquoi la méthode get devrait-elle être placée dans la classe d'outils CodeUtils, mais dans la classe d'implémentation de la couche métier ?
    insérez la description de l'image ici

  • Si nous le faisions, nous constaterions que nos annotations n'ont pas du tout pris effet. En effet, nos annotations ne sont pas chargées, nous ne pouvons rendre nos annotations efficaces qu'en chargeant cette méthode selon le formulaire de chargement du bean.

  • C'est-à-dire que le get() direct ne va pas dans le conteneur Spring et que l'annotation n'est pas chargée. Et codeUtils.get(), codeUtils crée notre classe d'outils, nous la mettons dans le conteneur Spring, de sorte que l'annotation de chargement prendra effet

​ Pour la fonction de vérification du code de vérification, il est recommandé de le mettre dans la classe outil.

Étape ⑤ : Définir la stratégie de génération du code de vérification et la fonction de lecture du code de vérification en fonction du numéro de téléphone mobile

@Component
public class CodeUtils {
    
    
    private String [] patch = {
    
    "000000","00000","0000","000","00","0",""};

    public String generator(String tele){
    
    
        int hash = tele.hashCode();
        int encryption = 20206666;
        long result = hash ^ encryption;
        long nowTime = System.currentTimeMillis();
        result = result ^ nowTime;
        long code = result % 1000000;
        code = code < 0 ? -code : code;
        String codeStr = code + "";
        int len = codeStr.length();
        return patch[len] + codeStr;
    }

    @Cacheable(value = "smsCode",key="#tele")
    public String get(String tele){
    
    
        return null;
    }
}

Étape ⑥ : Définir l'interface de la couche Web de la fonction de code de vérification, une méthode est utilisée pour fournir le numéro de téléphone mobile pour obtenir le code de vérification, et une méthode est utilisée pour fournir le numéro de téléphone mobile et le code de vérification pour la vérification

@RestController
@RequestMapping("/sms")
public class SMSCodeController {
    
    
    @Autowired
    private SMSCodeService smsCodeService;
    
    @GetMapping
    public String getCode(String tele){
    
    
        String code = smsCodeService.sendCodeToSMS(tele);
        return code;
    }
    
    @PostMapping
    public boolean checkCode(SMSCode smsCode){
    
    
        return smsCodeService.checkCode(smsCode);
    }
}

Je suppose que tu aimes

Origine blog.csdn.net/zyb18507175502/article/details/126403322
conseillé
Classement