[Serie SpringBoot] Solución de caché

Descripción general del almacenamiento en caché

La función principal de las aplicaciones de nivel empresarial es el procesamiento de la información. Cuando es necesario leer los datos, el rendimiento general del sistema es bajo debido a la eficiencia de acceso limitada de la base de datos.

inserte la descripción de la imagen aquí

La aplicación trata directamente con la base de datos y la eficiencia de acceso es baja.

Para mejorar el fenómeno anterior, los desarrolladores generalmente establecen un mecanismo de almacenamiento de datos temporal entre la aplicación y la base de datos.Los datos en esta área se almacenan en la memoria, y la velocidad de lectura y escritura es rápida, lo que puede resolver el problema de manera efectiva. de baja eficiencia de acceso a la base de datos. Esta zona de almacenamiento temporal de datos es la caché .

inserte la descripción de la imagen aquí

Después de usar el caché, la aplicación se ocupa del caché, el caché se ocupa de la base de datos y se mejora la eficiencia del acceso a los datos.

缓存Es un medio entre el medio de almacenamiento permanente de datos y la aplicación.medio de almacenamiento temporal de datos

  • El uso de un caché puede reducir efectivamente la cantidad de procesos de lectura de datos de baja velocidad (como la E/S del disco) y mejorar el rendimiento del sistema.
  • El caché no solo se puede utilizar para mejorar la eficiencia de lectura de datos de los medios de almacenamiento permanentes, sino que también proporciona espacio de almacenamiento de datos temporal.

A veces, incluso podemos construir cachés de varios niveles:
inserte la descripción de la imagen aquí

Springboot proporciona una solución para integrar casi todas las tecnologías de almacenamiento en caché del mercado. Comencemos juntos el viaje de la integración del almacenamiento en caché de Springboot.

Solución de almacenamiento en caché integrada de SpringBoot

La tecnología springboot proporciona una solución de almacenamiento en caché integrada, que puede ayudar a los desarrolladores a activar rápidamente la tecnología de almacenamiento en caché y usar la tecnología de almacenamiento en caché para realizar operaciones de datos rápidas, como leer datos almacenados en caché y escribir datos en el caché .

Paso 1 : Importe el iniciador correspondiente a la tecnología de almacenamiento en caché proporcionada por springboot

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

Paso 2 : habilite el almacenamiento en caché, anote @EnableCaching arriba de la clase de arranque para configurar el programa springboot para usar el almacenamiento en caché

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

Paso ③ : Establezca si usar el caché para los datos de la operación

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

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

En el método comercial, use la anotación @Cacheable para declarar que el valor de retorno del método actual se coloca en la memoria caché, lo que especifica la ubicación de almacenamiento de la memoria caché y el nombre correspondiente al valor de retorno del método actual almacenado en la memoria caché. . En el ejemplo anterior, el atributo de valor describe la ubicación de almacenamiento de la memoria caché, que puede entenderse como un nombre de espacio de almacenamiento. El atributo clave describe el nombre de los datos almacenados en la memoria caché. Utilice #id para leer el valor de identificación en el parámetro formal como el nombre de caché .

Después de usar la anotación @Cacheable, realice la operación actual. Si se encuentra que el nombre correspondiente no tiene datos en el caché, leerá los datos normalmente y luego los colocará en el caché; si el nombre correspondiente tiene datos en el caché, finalizará la ejecución del método comercial actual y volverá directamente a la caché.datos en .

Enviamos solicitudes varias veces en PostMan:
inserte la descripción de la imagen aquí
en nuestros registros, podemos ver que solo la primera vez que se manipula la base de datos, y luego los datos se toman del caché:
inserte la descripción de la imagen aquí

Además de proporcionar la solución de almacenamiento en caché predeterminada, la tecnología de almacenamiento en caché proporcionada por SpringBoot también puede integrar otras tecnologías de almacenamiento en caché y unificar la interfaz para facilitar el desarrollo y la gestión de tecnologías de almacenamiento en caché:

  • Genérico
  • JCache
  • Ehcache
  • avellana
  • Infinispan
  • Base de sofá
  • Redis
  • cafeína
  • Sencillo (predeterminado)
  • memcached

SpringBoot integra el almacenamiento en caché de Ehcache

Comencemos Springboot para integrar varias tecnologías de almacenamiento en caché, el primero en integrar la tecnología Ehcache. Ehcache es una tecnología de almacenamiento en caché. El uso de Springboot para integrar Ehcache es en realidad cambiar la implementación de la tecnología de almacenamiento en caché. No hay mucho que decir, solo abra todo

Paso 1 : Importar las coordenadas de Ehcache

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

¿Por qué no importar aquí el motor de arranque de Ehcache, sino importar las coordenadas técnicas? De hecho, springboot integra la tecnología de almacenamiento en caché en un formato general. No importa qué tecnología de almacenamiento en caché integre, la implementación ha cambiado y el método de operación es el mismo . Esto también refleja las ventajas de la tecnología springboot y unifica el método de integración de tecnologías similares.

Paso 2 : Configure la tecnología de caché para usar Ehcache

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

El tipo de caché de configuración es ehcache.Es necesario explicar aquí que la tecnología de almacenamiento en caché actual que Springboot puede integrar incluye ehcach, por lo que se puede escribir así. De hecho, este tipo no se puede escribir de manera casual, y no se puede integrar simplemente escribiendo un nombre.

Dado que la configuración de ehcache tiene un formato de archivo de configuración independiente, también es necesario especificar el archivo de configuración de ehcache para facilitar la lectura de la configuración correspondiente

<?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>

Tenga en cuenta que en el caso del código de verificación del teléfono móvil, la ubicación donde se guardan los datos es smsCode

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

Esta configuración debe garantizar que haya una configuración con un nombre de espacio de caché llamado smsCode en ehcache, que debe unificarse antes y después.En el proceso de desarrollo empresarial, se establecen diferentes estrategias de almacenamiento en caché mediante la configuración de cachés con diferentes nombres (atributos de nombre), que se aplican a diferentes datos almacenados en caché..

En este punto, springboot ha completado la integración de Ehcache. Se puede encontrar que el código original no se ha modificado, y el proveedor de caché solo se puede cambiar agregando un conjunto de configuraciones. Esta es también la ventaja de que springboot proporciona un unificado interfaz de operación de caché No afecta la escritura del código original.

Resumir

  1. springboot usa Ehcache como caché para implementar coordenadas que deben importarse a Ehcache
  2. Modifique la configuración, configure el proveedor de caché como ehcache y proporcione el archivo de configuración de caché correspondiente

SpringBoot integra caché Redis

Compare el proceso de uso de Ehcache, agregue coordenadas, cambie el tipo de implementación de caché a ehcache y configure Ehcache. ¿Qué pasa si redis todavía se usa para el almacenamiento en caché? Exactamente lo mismo, agregue coordenadas, cambie el tipo de implementación de caché a redis y configure redis.La única diferencia es que la configuración de redis se puede configurar directamente en el archivo yml sin crear un archivo de configuración separado..

Paso 1 : Importa las coordenadas de redis

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

Paso 2 : configure la tecnología de caché para usar redis

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

Recuerde que al usar la tecnología de almacenamiento en caché redis, el servidor debe estar encendido

​ Si necesita configurar redis como caché, preste atención a no configurar el redis original, sino configurar redis como caché para usar la configuración relevante, que pertenece al nodo spring.cache.redis, tenga cuidado de no escribir el Lugar equivocado.

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

Anotación de parámetros:

  • time-to-live establece la vida útil del caché
  • use-key-prefix no utiliza el prefijo de la clave, podemos ver que cuando se establece en verdadero, el smsCode anterior desaparece, en este caso, el riesgo es muy alto y los datos pueden repetirse.
    inserte la descripción de la imagen aquí
  • key-prefix: especifica el prefijo. Podemos ver key-prefix: sms_el efecto:
    inserte la descripción de la imagen aquí
  • Si usamos key-prefixcon use-key-prefix:
    inserte la descripción de la imagen aquí
    inserte la descripción de la imagen aquí
  • cache-null-values: si almacenar en caché valores nulos

Resumir

  1. springboot usa redis como caché para implementar coordenadas que deben importarse a redis
  2. Modifique la configuración, configure el proveedor de caché como redis y proporcione la configuración de caché correspondiente

SpringBoot integra el almacenamiento en caché de Memcached

En la actualidad, hemos dominado las formas de configuración de tres soluciones de almacenamiento en caché, a saber, el caché integrado springboot, ehcache y redis.En esta sección, estudiaremos un caché doméstico popular, memcached.

De acuerdo a la rutina anterior, no es tedioso cambiar el caché, pero springboot no soporta el uso de memcached como su solución de caché, es decir, no hay opción de configuración para memcached en el atributo type, por lo que el método de procesamiento necesita ser cambiado aquí. Instalar memcached antes de la integración.

Instalar

Dirección de descarga del paquete de instalación de la versión de Windows: https://www.runoob.com/memcached/window-install-memcached.html

​ El paquete de instalación descargado es un archivo zip que se puede utilizar después de la descompresión.Después de la descompresión, se obtendrán los siguientes archivos

inserte la descripción de la imagen aquí

​ El archivo ejecutable tiene solo un memcached.exe, que se puede usar para iniciar memcached como un servicio del sistema. Aparecerá un mensaje de error al ejecutar este archivo, de la siguiente manera:

inserte la descripción de la imagen aquí

​ El motivo del problema aquí es que necesita usar privilegios de administrador al registrar los servicios del sistema. La cuenta actual tiene privilegios insuficientes y la instalación del servicio falla. Cambie los privilegios de la cuenta de administrador para iniciar la línea de comando.

inserte la descripción de la imagen aquí

Luego ejecute el comando para instalar el servicio nuevamente, de la siguiente manera:

memcached.exe -d install

​ Después de instalar el servicio, puede usar los comandos para iniciar y detener el servicio, de la siguiente manera:

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

También puede cambiar el estado del servicio en el administrador de tareas

inserte la descripción de la imagen aquí

Cambiar caché a Memcached

Dado que Springboot no incluye Memcached como una solución de almacenamiento en caché, el uso de Memcached debe usarse mediante codificación manual, por lo que las rutinas anteriores no son aplicables y debe escribirlas usted mismo.

​ Actualmente, Memcached proporciona tres tecnologías de cliente, a saber, Memcached Client for Java, SpyMemcached y Xmemcached, entre ellas, el cliente con mejores indicadores de rendimiento es Xmemcached, que se utiliza como tecnología de implementación del cliente para esta integración. Comencemos a usar Xmemcached

Selección de tecnología del clienteinserte la descripción de la imagen aquí

Paso 1 : Importa las coordenadas de xmemcached

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

Paso 2 : configurar memcached y crear una clase de configuración para memcached

Debido a que SpringBoot no integra Memcached, no se puede configurar en el archivo de configuración. Solo puede escribir clases de configuración manualmente

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

La dirección del servidor y el puerto de memcached están escritos en XMemcachedClientBuilder.

​ memcached tiene como valor predeterminado el puerto de servicio externo 11211.

Paso 3 : use el cliente xmemcached para operar el caché e inyectar el objeto 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);
    }
}

El método memcachedClient.set() lanza una excepción, donde:
el primer parámetro: especifica la clave almacenada en caché
El segundo parámetro: especifica el tiempo de caducidad. 0 significa que nunca caduca, 10 significa que 10s es válido
El tercer parámetro: el valor almacenado en caché especificado El
método memcachedClient.get() también generará una excepción

Para establecer el valor en el caché, use la operación set y use la operación get para recuperar el valor, que en realidad está más en línea con los hábitos de nuestros desarrolladores.

En el código anterior, la configuración del servidor está codificada en el código, y estos datos se extraen y se convierten en un atributo de configuración independiente.

Definir propiedades de configuración

El siguiente proceso adopta el método de configuración de propiedades

  • Defina la clase de configuración, cargue las propiedades de configuración necesarias y lea la información del nodo memcached en el archivo de configuración

    @Component
    @ConfigurationProperties(prefix = "memcached")
    @Data
    public class XMemcachedProperties {
          
          
        private String servers;
        private int poolSize;
        private long opTimeout;
    }
    
  • Definir la información del nodo memcached

    memcached:
      servers: localhost:11211
      poolSize: 10
      opTimeout: 3000
    
  • Cargar información en la clase de configuración 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;
    }
}

Resumir

  1. Después de instalar Memcached, se debe iniciar el servicio correspondiente antes de que pueda proporcionar la función de caché externa. La instalación del servicio Memcached debe basarse en los privilegios de administrador del sistema de Windows.
  2. Dado que Springboot no proporciona una solución de integración de caché para Memcached, es necesario crear la caché de operaciones del cliente xmemcached en forma de codificación manual.
  3. Después de importar las coordenadas de xmemcached, cree una clase de configuración de memcached y registre el bean correspondiente a MemcachedClient para operar el caché
  4. Las propiedades necesarias para inicializar el objeto MemcachedClient se pueden cargar en forma de una clase de propiedad de configuración personalizada

SpringBoot integra el almacenamiento en caché jetcache

Actualmente, los cachés que usamos son A o B. ¿Se pueden usar A y B juntos? La integración de cachés de Springboot solo se basa en el uso de cachés. Si el caché en sí no admite el uso de AB al mismo tiempo, Springboot no puede hacerlo. Por lo tanto, para resolver el problema de usar cachés AB juntos, debe debe encontrar un caché que admita tanto AB como AB. El caché se usa en conjunto, ¿existe tal caché? Realmente lo hay, produjo Ali, jetcache.

La solución de Ali resuelve nuestros dos problemas originales:
① Las soluciones de caché originales que usamos se configuraron en yml, se configuraron en xml y se controlaron en la clase de configuración. Es muy complicado y desordenado.②
Cuando estamos haciendo el esquema de almacenamiento en caché, usamos el formulario local, como ehcache, simple (predeterminado), y no configuramos la dirección IP y el puerto cuando los usamos. O usamos una solución remota, como redis, memcached, cuando las usamos, configuramos la dirección IP y el puerto. Hay planes locales. No hay esquema remoto, sino solo la neutralización de los dos esquemas. Solo necesitamos la neutralización de los dos porque la solución remota inevitablemente implicará problemas de red y su velocidad será lenta, pero resuelve el problema de la caché compartida entre varios servidores. Y solucionamos el problema de la velocidad con local, pero no el problema de compartir.

Estrictamente hablando, jetcache no es una solución de almacenamiento en caché. Solo se puede decir que es un marco de almacenamiento en caché, y luego otros cachés se administran en jetcache, de modo que los cachés AB se pueden usar juntos . Y jetcache se refiere a la idea de springboot de integrar el almacenamiento en caché, y el uso general de la tecnología es muy similar a la idea de la solución de almacenamiento en caché de springboot. Primero usemos jetcache y luego hablemos de algunas funciones pequeñas en él.

Antes de hacerlo, aclare que jetcache no puede tomar dos cachés juntos. Actualmente, jetcache admite dos tipos de esquemas de almacenamiento en caché: almacenamiento en caché local y almacenamiento en caché remoto, que son los siguientes:

  • Caché local (Local)
    • LinkedHashMap
    • Cafeína
  • Caché remota (remota)
    • redis
    • Tres

Solución remota pura

Paso 1 : Importe springboot para integrar el iniciador de coordenadas correspondiente a jetcache. El esquema remoto predeterminado utilizado por la coordenada actual es redis

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

Paso 2 : Configuración básica del esquema remoto

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

maxTotal indica el número máximo de conexiones

El poolConfig es un elemento obligatorio; de lo contrario, se informará un error.

Paso 3 : habilite el almacenamiento en caché, marque la anotación @EnableCreateCacheAnnotation arriba de la clase de arranque para configurar el programa springboot para crear un caché en forma de anotaciones

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

Paso 4 : cree el objeto de caché Cache y use la anotación @CreateCache para marcar la información del caché actual y luego use la API del objeto Cache para operar el caché, colocar el caché de escritura y obtener el caché de lectura.

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

Esto es para crear un objeto de caché, que puede entenderse como la definición de un hashmap, por supuesto, hay otras configuraciones

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

Esta oración es equivalente a decirle a jetcache que este es un objeto de caché.

  • name es el espacio de nombres, equivalente al valor en Ehcache
  • expire es el tiempo de caché, la unidad predeterminada es segundos
  • timeUnit se utiliza para establecer la unidad de tiempo de caché. Puede utilizar este elemento de configuración cuando no desee utilizar la unidad predeterminada.

A través del jetcache mencionado anteriormente que usa el esquema remoto para conectarse a redis, se puede ver que la operación de la interfaz cuando jetcache opera el caché está más en línea con los hábitos del desarrollador.Al usar el caché, el objeto de caché Cache se obtiene primero, se ingresan los datos y se sacan los datos, lo cual es más simple y fácil de entender. . Y cuando jetcache opera el caché, puede establecer el tiempo de caducidad para un objeto de caché y colocar el mismo tipo de datos en el caché para facilitar la gestión del período efectivo .

​ El esquema anterior utiliza el caché predeterminado definido en la configuración,De hecho, este valor predeterminado es un nombre, puede escribirlo de forma casual o puede agregarlo de forma casual.. Por ejemplo, para agregar otra solución de almacenamiento en caché, consulte la siguiente configuración:

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

Si desea utilizar el caché con el nombre sms, debe especificar el área de parámetros al crear el caché y declarar el caché correspondiente.

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

solución local pura

En el esquema remoto, remoto se usa en la configuración para indicar remoto y local es local, pero el tipo es diferente.

Paso 1 : Importe springboot para integrar el iniciador de coordenadas correspondiente a jetcache

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

Paso 2 : Configuración básica de caché local

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

Para acelerar la velocidad de coincidencia de claves durante la adquisición de datos, jetcache requiere un convertidor de tipos para especificar la clave. En pocas palabras, si proporciona un objeto como clave, primero lo convierto en una cadena usando el convertidor de tipo de clave y luego lo guardo. Cuando se obtienen los datos, el objeto dado todavía se convierte primero en una cadena y luego se compara de acuerdo con la cadena. Dado que jetcache es la tecnología de Ali, se recomienda utilizar fastjson de Ali como convertidor de tipo de clave aquí.

Paso ③ : habilitar el almacenamiento en caché

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

Paso 4 : al crear el objeto de caché Caché, marque el uso actual del caché 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 controla si el caché actual usa el caché local o el caché remoto Configure cacheType=CacheType.LOCAL para usar el caché local.

Escenario Local + Remoto

Tanto los métodos locales como los remotos están disponibles ¿Cómo configurar los dos esquemas juntos? De hecho, basta con combinar las dos configuraciones.

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

Al crear un caché, configure cacheType en AMBOS, es decir, el caché local y el caché remoto se usan al mismo tiempo.

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

​ Si cacheType no está configurado, el valor predeterminado es REMOTE, es decir, solo se utiliza el esquema de caché remota. Para la configuración de jetcache, consulte la siguiente información

Atributos valores predeterminados ilustrar
jetcache.statIntervalMinutes 0 Intervalo de estadísticas, 0 significa que no hay estadísticas
jetcache.hiddenPackages ninguna Cuando el nombre se genera automáticamente, oculta el prefijo del nombre del paquete especificado
jetcache.[local|remoto].${área}.type ninguna Tipo de caché, soporte local linkedhashmap, cafeína, soporte remoto redis, tair
jetcache.[local|remoto].${área}.keyConvertor ninguna convertidor de claves, actualmente solo es compatible con fastjson
jetcache.[local|remoto].${área}.valueEncoder Java Solo es necesario especificar el caché de tipo remoto, java y kryo opcionales
jetcache.[local|remoto].${área}.valueDecoder Java Solo es necesario especificar el caché de tipo remoto, java y kryo opcionales
jetcache.[local|remoto].${área}.limit 100 Solo se debe especificar el tipo local de caché, el número máximo de elementos de la instancia de caché
jetcache.[local|remoto].${área}.expireAfterWriteInMillis Sin precedentes Tiempo de caducidad predeterminado, en milisegundos
jetcache.local.${área}.expireAfterAccessInMillis 0 Solo las cachés de tipo local son válidas, milisegundos, intervalo máximo de inactividad

Las soluciones anteriores solo admiten el control manual de la memoria caché, pero la memoria caché del método en la solución springcache es particularmente útil. Agregue una anotación a un método y el método usará automáticamente la memoria caché. Jetcache también proporciona una función correspondiente, a saber, el almacenamiento en caché de métodos.

caché de métodos

jetcache proporciona una solución de almacenamiento en caché de métodos, pero el nombre ha cambiado. Simplemente use la anotación @Cached arriba de la interfaz de operación correspondiente

Paso 1 : Importe springboot para integrar el iniciador de coordenadas correspondiente a jetcache

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

Paso 2 : configurar el caché

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

Dado que la memoria caché de redis no admite guardar objetos, es necesario configurar cómo realizar la conversión de tipo para redis cuando los datos de tipo de objeto ingresan en redis. El keyConvertor debe configurarse para indicar el método de conversión de tipo de la clave y, al mismo tiempo, se debe marcar el método de tipo de conversión del valor. Cuando el valor ingresa a redis, es de tipo java y se marca valueEncode. como Java.

Tenga en cuenta que para implementar el valor del tipo de objeto dentro y fuera de redis, es necesario asegurarse de que los datos de tipo objeto dentro y fuera de redis deben implementar la interfaz de serialización.

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

Paso ③ : active la función de caché de método cuando el caché esté habilitado,Y configure basePackages para indicar en qué paquetes está habilitado el método de almacenamiento en caché

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

Paso 4 : use la anotación @Cached para marcar el método actual para usar el caché

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

resultado:
inserte la descripción de la imagen aquí

Sincronización de datos para escenarios remotos

Dado que los datos guardados por redis en el esquema remoto pueden ser compartidos por varios clientes, existe un problema de sincronización de datos. Jetcache proporciona 3 anotaciones para resolver este problema, sincronizando los datos almacenados en caché durante las operaciones de actualización y eliminación, y actualizando periódicamente los datos al leer el caché.

actualizar caché

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

borrar caché

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

Actualizar periódicamente el caché

Pensando en escenarios de uso: si hay una tabla, ahora el sistema A puede modificar esta tabla y el sistema B también puede modificar esta tabla. Ahora el sistema A ha leído los datos de esta tabla en el caché y, al mismo tiempo, el sistema B ha cambiado los datos de esta tabla. ¿Esto no causa un error (los datos en la memoria y los datos de la tabla no están sincronizados)? El sistema A no sabe que la tabla ha cambiado en este momento y todavía está usando los datos antiguos en el caché. Para decirlo sin rodeos, el sistema B no le dirá al sistema A que la mesa ha cambiado después de operar la mesa.

Podemos usar @CacheRefresh para actualizar el caché (los datos en el caché en este momento) regularmente, la unidad predeterminada es segundos

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

Si encuentra que cada vez que va a la base de datos en lugar de al caché, puede considerar si el tiempo de caché es demasiado corto.

informe de datos

jetcache también proporciona una función de informe de datos simple para ayudar a los desarrolladores a ver rápidamente la información de aciertos de caché, solo agregue una configuración

jetcache:
  statIntervalMinutes: 1

​ Después de la configuración, la salida de datos de la memoria caché en la consola cada 1 minuto (unidad predeterminada)

[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
---------+-------+-------+------+-------+-------+---------+--------------+--------------

Resumir

  1. Jetcache es una solución de almacenamiento en caché similar a Springcache. No tiene una función de almacenamiento en caché. Proporciona una solución de almacenamiento en caché de varios niveles que utiliza el almacenamiento en caché local y el almacenamiento en caché remoto.
  2. Las soluciones de almacenamiento en caché proporcionadas por jetcache están limitadas por las soluciones admitidas actualmente. Hay dos tipos de cachés locales y dos tipos de cachés remotas.
  3. Preste atención al problema de conversión de tipo cuando los datos ingresan al caché remoto
  4. jetcache proporciona almacenamiento en caché de métodos y proporciona las funciones de actualización y actualización de caché correspondientes
  5. Jetcache proporciona un informe de aciertos de información de caché simple para facilitar a los desarrolladores el seguimiento de aciertos de datos de caché en tiempo real.

SpringBoot integra el almacenamiento en caché j2cache

j2cache es un marco de integración de caché, que puede proporcionar una solución de integración de caché, de modo que varios cachés se pueden usar juntos y no proporciona una función de caché por sí mismo.

Jetcache puede construir cachés de varios niveles dentro de un rango limitado, pero no es lo suficientemente flexible para hacer coincidir los cachés a voluntad. Esta sección presenta un marco de integración de caché, j2cache, que se puede usar con soluciones de almacenamiento en caché a voluntad. Expliquemos cómo usar este marco de almacenamiento en caché, tomando como ejemplo la integración de Ehcache y redis:

Paso 1 : Importar coordenadas 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>

El iniciador de j2cache contiene coordenadas redis de forma predeterminada. Se recomienda oficialmente usar redis como caché secundaria, por lo que no es necesario importar coordenadas redis aquí.

Paso 2 : Configure los cachés de primer y segundo nivel, y configure el método de transferencia de datos entre los cachés de primer y segundo nivel. La configuración se escribe en un archivo denominado j2cache.properties. Si usa ehcache, también necesita agregar el archivo de configuración de ehcache por separado

# 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 configuración aquí no se puede configurar arbitrariamente y debe consultar las instrucciones de configuración oficiales. Por ejemplo, si un proveedor de nivel 1 elige ehcache, el nombre del proveedor es solo ehcache, pero cuando un proveedor de nivel 2 elige redis, debe escribir un nombre de clase de proveedor de Redis integrado en Spring dedicado SpringRedisProvider, y este nombre no está disponible en todos los paquetes redis. , tampoco incluidos en el paquete de primavera. Por lo tanto, para configurar j2cache, debe consultar la configuración del documento oficial, y también debe encontrar un paquete de integración dedicado e importar las coordenadas correspondientes antes de que pueda usarse.

​ La configuración más importante de los cachés de primer y segundo nivel es el método de comunicación de datos entre los dos. Este tipo de configuración no se configura arbitrariamente, y los métodos de comunicación de datos proporcionados por diferentes soluciones de almacenamiento en caché son muy diferentes. Debe consulta el sitio web oficial documento para establecer.

Paso ③ : Usar caché

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

​ El uso de j2cache es similar a jetcache, pero no necesita abrir el interruptor para usarlo, simplemente defina el objeto de caché y utilícelo, el nombre del objeto de caché es CacheChannel.

El uso de j2cache no es complicado, y la configuración es el núcleo de j2cache.Después de todo, es un marco de almacenamiento en caché integrado. Hay demasiadas configuraciones relacionadas con la memoria caché. Puede consultar la descripción en el archivo j2cache.properties en el paquete principal de j2cache-core. como sigue:

#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

Resumir

  1. j2cache es un marco de almacenamiento en caché que no tiene una función de almacenamiento en caché por sí mismo. Proporciona soluciones para integrar múltiples cachés.
  2. j2cache necesita configurar todos los niveles de caché a través de una configuración compleja, así como la forma de intercambio de datos entre cachés
  3. La interfaz de operación j2cache se implementa a través de CacheChannel

Adjunto: Caso de código de verificación de teléfono móvil

Este caso utiliza la solución de almacenamiento en caché integrada de SpringBoot

Para facilitar la demostración de varias tecnologías de almacenamiento en caché a continuación, creamos un entorno de caso para códigos de verificación móviles para simular el proceso de uso de caché para guardar códigos de verificación móviles.

Los requisitos del caso del código de verificación móvil son los siguientes:

  • Ingrese el número de teléfono móvil para obtener el código de verificación y envíe el documento de la organización al usuario en forma de SMS (simulación de página)
  • Ingrese el número de teléfono móvil y el código de verificación para verificar el resultado

Para describir las operaciones anteriores, creamos dos interfaces de capa de presentación, una se usa para simular el proceso de envío de mensajes SMS, de hecho, se genera un código de verificación de acuerdo con el número de teléfono móvil proporcionado por el usuario y luego se almacena en el caché, y el otro se usa para simular la verificación del código de verificación. El proceso es en realidad usar el número de teléfono móvil entrante y el código de verificación para hacer coincidir, y devolver el resultado final de la coincidencia. El código de simulación de este caso se produce directamente a continuación, y la tecnología de almacenamiento en caché integrada proporcionada por springboot en el ejemplo anterior se usa para completar la producción del caso actual.

Paso 1 : Importe el iniciador correspondiente a la tecnología de almacenamiento en caché proporcionada por springboot

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

Paso 2 : habilite el almacenamiento en caché, anote @EnableCaching arriba de la clase de arranque para configurar el programa springboot para usar el almacenamiento en caché

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

Paso 3 : defina la clase de entidad correspondiente al código de verificación y encapsule los dos atributos del número de teléfono móvil y el código de verificación

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

Paso 4 : Defina la interfaz de la capa empresarial y la clase de implementación de la función del código de verificación

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

Después de obtener el código de verificación, el código de verificación debe obtenerse nuevamente cuando el código de verificación no es válido. Por lo tanto, la anotación @Cacheable no se puede usar en la función de obtener el código de verificación.La anotación @Cacheable es poner un valor si no hay valor en el caché y tomar un valor si hay un valor en el caché. La función aquí es solo generar el código de verificación y ponerlo en el caché, y no tiene la función de obtener el valor del caché, por lo que no se puede usar la anotación @Cacheable, y la función que solo guarda datos en el se debe usar caché, y se puede usar la anotación @CachePut. .

Algunas notas más aquí:

  • Si queremos obtener el valor del caché, podemos establecer un método separado (es decir, el método get en el código anterior), anotarlo con @Cacheable y dejar que el método devuelva nulo. El valor extraído de esta forma se asignará al valor de retorno del método

  • ¿Por qué el método get debe colocarse en la clase de herramienta CodeUtils, pero en la clase de implementación de la capa empresarial?
    inserte la descripción de la imagen aquí

  • Si lo hiciéramos, encontraríamos que nuestras anotaciones no surtieron efecto en absoluto. Esto se debe a que nuestras anotaciones no están cargadas, solo podemos hacer que nuestras anotaciones sean efectivas cargando este método de acuerdo con el formulario de carga de bean.

  • Es decir, el get() directo no va al contenedor Spring y la anotación no se carga. Y codeUtils.get(), codeUtils crea nuestra clase de herramienta, la colocamos en el contenedor Spring, por lo que la anotación de carga surtirá efecto.

Para la función de verificar el código de verificación, se recomienda ponerlo en la clase de herramienta.

Paso ⑤ : Defina la estrategia de generación del código de verificación y la función de lectura del código de verificación según el número de teléfono móvil

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

Paso ⑥ : defina la interfaz de la capa web de la función del código de verificación, se usa un método para proporcionar el número de teléfono móvil para obtener el código de verificación, y se usa un método para proporcionar el número de teléfono móvil y el código de verificación para la verificación

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

Supongo que te gusta

Origin blog.csdn.net/zyb18507175502/article/details/126403322
Recomendado
Clasificación