Uso e integración de Spring-Boot-Cache

1: abstracción de caché de primavera

Spring ha definido las interfaces org.springframework.cache.Cache y org.springframework.cache.CacheManager desde 3.1 para unificar diferentes tecnologías de almacenamiento en caché y admite el uso de anotaciones JCache (JSR-107) para simplificar nuestro desarrollo;

La interfaz de caché se define en la especificación del componente de caché e incluye una colección de varias operaciones de caché;

Bajo la interfaz Cache, Spring proporciona varias implementaciones de xxxCache, como RedisCache, EhCacheCache, ConcurrentMapCache, etc.;

Cada vez que se llama a un método que requiere almacenamiento en caché, Spring verificará si se ha llamado al método de destino especificado con los parámetros especificados; si es así, obtendrá directamente el resultado de la llamada al método del caché; si no, llamará al método y almacenar en caché el resultado. Volver al usuario. La siguiente llamada se obtendrá directamente del caché.

Debemos prestar atención a los dos puntos siguientes cuando utilizamos la abstracción de caché de Spring;

1. Determinar los métodos que deben almacenarse en caché y su estrategia de almacenamiento en caché.

2. Lea los datos previamente almacenados en caché del caché

2: Varios conceptos importantes y anotaciones en caché

nombre explicar
Cache Interfaz de caché, que define las operaciones de caché. Las implementaciones incluyen: RedisCache, EhCacheCache, ConcurrentMapCache, etc.
Administrador de caché Administrador de caché, gestiona varios componentes de caché
@caché Principalmente para la configuración del método, se puede almacenar en caché de acuerdo con los parámetros de solicitud del método.
@CacheEvict Vaciar el caché
@CachePut Asegúrese de que se llame al método y espere que el resultado se almacene en caché. La diferencia con @Cacheable es si el método se llama cada vez, lo que a menudo se usa para actualizaciones.
@EnableCaching Habilitar el almacenamiento en caché basado en anotaciones
generador de llaves Estrategia de generación de claves al almacenar datos en caché
fabricar en serie Estrategia de serialización de valores al almacenar datos en caché
@CacheConfig Configure de manera uniforme las propiedades de las anotaciones de caché de esta clase

@Cacheable/@CachePut/@CacheEvict parámetros principales

nombre explicar
valor El nombre del caché, definido en el archivo de configuración de Spring, debe especificar al menos un ejemplo: @Cacheable(value=”mycache”) o @Cacheable(value={”cache1”,”cache2”}
llave La clave de caché puede estar vacía. Si se especifica que se escriba de acuerdo con la expresión SpEL, si no se especifica, se combinará de acuerdo con todos los parámetros del método de forma predeterminada. Por ejemplo: @Cacheable(value="testcache", key ="#id")
condición La condición de la caché puede estar vacía, escrita en SpEL y devuelve verdadero o falso. Solo cuando sea verdadera, la caché se almacenará en caché o se borrará. Por ejemplo: @Cacheable(value="testcache",condition="#userName.length ()>2")
a menos que Negar el almacenamiento en caché. Cuando el resultado de la condición es VERDADERO, no se almacenará en caché. @Cacheable(value="testcache",a menos que="#userName.length()>2")
todas las entradas (@CacheEvict) Si se borra todo el contenido de la caché. El valor predeterminado es falso. Si se especifica verdadero, todas las cachés se borrarán inmediatamente después de llamar al método. Por ejemplo: @CachEvict(value="testcache", allEntries=true)
antes de la invocación (@CacheEvict) Si se debe borrar antes de que se ejecute el método. El valor predeterminado es falso. Si se especifica verdadero, el caché se borrará antes de que se ejecute el método. De manera predeterminada, si se lanza una excepción durante la ejecución del método, el caché no se borrará. Para ejemplo: @ CachEvict(value="testcache", beforeInvocation=true)

Tres: datos de contexto SpEL

Spring Cache proporciona algunos datos de contexto SpEL para que los usemos. La siguiente tabla está tomada directamente de la documentación oficial de Spring:

nombre Ubicación describir Ejemplo
nombre del método objeto raíz El nombre del método actualmente llamado. #root.nombredelmétodo
método objeto raíz El método que se está llamando actualmente. #nombre.del.método.raíz
objetivo objeto raíz La instancia del objeto de destino que se está llamando actualmente #root.objetivo
clase objetivo objeto raíz La clase del objeto de destino que se está llamando actualmente. #root.targetClass
argumentos objeto raíz La lista de parámetros del método actualmente llamado. #raíz.args[0]
cachés objeto raíz La lista de caché utilizada por la llamada al método actual. #root.caches[0].nombre
Nombre del argumento contexto de ejecución Los parámetros del método llamado actualmente, como findArtisan (artesano), se pueden obtener a través de #artsian.id #artsian.id
resultado contexto de ejecución El valor de retorno después de la ejecución del método (solo válido después de ejecutar el método, a menos que cacheEvict's beforeInvocation=false) #resultado

Aviso:

1. Cuando queremos usar los atributos del objeto raíz como clave, también podemos omitir "#root", porque Spring usa los atributos del objeto raíz de forma predeterminada. como

@Cacheable(clave = “Clase de destino + Nombre del método +#p0”)

2. Cuando usamos parámetros de método, podemos usar directamente "#nombre de parámetro" o "#índice de parámetro". como:

@Cacheable(valor=“usuarios”, clave="#id")

@Cacheable(valor=“usuarios”, clave="#p0")

SpEL ofrece una variedad de operadores

tipo operador
relación <,>,<=,>=,==,!=,lt,gt,le,ge,eq,ne
aritmética +,- ,* ,/,%,^
lógica &&,ll,!,y,o,no,entre,instanciade
condición ?: (ternario),?: (elvis)
expresión regular partidos
Otros tipos ps

Los puntos de conocimiento anteriores son adecuados para que los consulte cuando los olvide. ¡Comencemos oficialmente a aprender!

Cuatro: empezar

Entorno: arranque de primavera 2.0.3

IDEA: IDEA

1. Debes importar dependencias antes de comenzar a usarlo.

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

2. Luego anote @EnableCaching en la clase de inicio para habilitar el almacenamiento en caché.

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

3. Caché @Cacheable

@Cacheable注解会先查询是否已经有缓存,有会使用缓存,没有则会执行方法并缓存。

    @Cacheable(value = "emp" ,key = "targetClass + methodName +#p0")
    public List<NewJob> queryAll(User uid) {
    
    
        return newJobDao.findAllByUid(uid);
    }

此处的value是必需的,它指定了你的缓存存放在哪块命名空间。

此处的key是使用的spEL表达式,参考上章。这里有一个小坑,如果你把methodName换成method运行会报错,观察它们的返回类型,原因在于methodName是String而methoh是Method。

此处的User实体类一定要实现序列化public class User implements Serializable,否则会报java.io.NotSerializableException异常。

到这里,你已经可以运行程序检验缓存功能是否实现。

深入源码,查看它的其它属性

我们打开@Cacheable注解的源码,可以看到该注解提供的其他属性,如:

String[] cacheNames() default {
    
    }; //和value注解差不多,二选一
String keyGenerator() default ""; //key的生成器。key/keyGenerator二选一使用
String cacheManager() default ""; //指定缓存管理器
String cacheResolver() default ""; //或者指定获取解析器
String condition() default ""; //条件符合则缓存
String unless() default ""; //条件符合则不缓存
boolean sync() default false; //是否使用异步模式

4.配置@CacheConfig

当我们需要缓存的地方越来越多,你可以使用@CacheConfig(cacheNames = {“myCache”})注解来统一指定value的值,这时可省略value,如果你在你的方法依旧写上了value,那么依然以方法的value值为准。

使用方法如下:

@CacheConfig(cacheNames = {
    
    "myCache"})
public class BotRelationServiceImpl implements BotRelationService {
    
    
    @Override
    @Cacheable(key = "targetClass + methodName +#p0")//此处没写value
    public List<BotRelation> findAllLimit(int num) {
    
    
        return botRelationRepository.findAllLimit(num);
    }
    .....
}

查看它的其它属性

String keyGenerator() default "";  //key的生成器。key/keyGenerator二选一使用
String cacheManager() default "";  //指定缓存管理器
String cacheResolver() default ""; //或者指定获取解析器

5.更新@CachePut

@CachePut注解的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用 。简单来说就是用户更新缓存数据。但需要注意的是该注解的value 和 key 必须与要更新的缓存相同,也就是与@Cacheable 相同。示例:

    @CachePut(value = "emp", key = "targetClass + #p0")
    public NewJob updata(NewJob job) {
    
    
        NewJob newJob = newJobDao.findAllById(job.getId());
        newJob.updata(job);
        return job;
    }
 
    @Cacheable(value = "emp", key = "targetClass +#p0")//清空缓存
    public NewJob save(NewJob job) {
    
    
        newJobDao.save(job);
        return job;
    }

查看它的其它属性

String[] cacheNames() default {
    
    }; //与value二选一
String keyGenerator() default "";  //key的生成器。key/keyGenerator二选一使用
String cacheManager() default "";  //指定缓存管理器
String cacheResolver() default ""; //或者指定获取解析器
String condition() default ""; //条件符合则缓存
String unless() default ""; //条件符合则不缓存

6.清除@CacheEvict

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空 。

属性 解释 示例
allEntries 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 @CachEvict(value=”testcache”,allEntries=true)
beforeInvocation 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 @CachEvict(value=”testcache”,beforeInvocation=true)

示例:

    @Cacheable(value = "emp",key = "#p0.id")
    public NewJob save(NewJob job) {
    
    
        newJobDao.save(job);
        return job;
    }
 
    //清除一条缓存,key为要清空的数据
    @CacheEvict(value="emp",key="#id")
    public void delect(int id) {
    
    
        newJobDao.deleteAllById(id);
    }
 
    //方法调用后清空所有缓存
    @CacheEvict(value="accountCache",allEntries=true)
    public void delectAll() {
    
    
        newJobDao.deleteAll();
    }
 
    //方法调用前清空所有缓存
    @CacheEvict(value="accountCache",beforeInvocation=true)
    public void delectAll() {
    
    
        newJobDao.deleteAll();
    }

其他属性

String[] cacheNames() default {
    
    }; //与value二选一
String keyGenerator() default "";  //key的生成器。key/keyGenerator二选一使用
String cacheManager() default "";  //指定缓存管理器
String cacheResolver() default ""; //或者指定获取解析器
String condition() default ""; //条件符合则清空

7.组合@Caching

有时候我们可能组合多个Cache注解使用,此时就需要@Caching组合多个注解标签了。

@Caching(cacheable = {
    
    
        @Cacheable(value = "emp",key = "#p0"),
        ...
},
put = {
    
    
        @CachePut(value = "emp",key = "#p0"),
        ...
},evict = {
    
    
        @CacheEvict(value = "emp",key = "#p0"),
        ....
})
public User save(User user) {
    
    
    ....
}

下面讲到的整合第三方缓存组件都是基于上面的已经完成的步骤,所以一个应用要先做好你的缓存逻辑,再来整合其他cache组件。

五:整合EHCACHE

Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。

1.导入依赖

整合ehcache必须要导入它的依赖。

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

2.yml配置

需要说明的是config: classpath:/ehcache.xml可以不用写,因为默认就是这个路径。但ehcache.xml必须有。

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

3.ehcache.xml

在resources目录下新建ehcache.xml,注释啥的应该可以说相当详细了

<ehcache>
    <!--
        磁盘存储:将缓存中暂时不使用的对象,转移到硬盘,类似于Windows系统的虚拟内存
        path:指定在硬盘上存储对象的路径
        path可以配置的目录有:
            user.home(用户的家目录)
            user.dir(用户当前的工作目录)
            java.io.tmpdir(默认的临时目录)
            ehcache.disk.store.dir(ehcache的配置目录)
            绝对路径(如:d:\\ehcache)
        查看路径方法:String tmpDir = System.getProperty("java.io.tmpdir");
     -->
    <diskStore path="java.io.tmpdir" />
 
    <!--
        defaultCache:默认的缓存配置信息,如果不加特殊说明,则所有对象按照此配置项处理
        maxElementsInMemory:设置了缓存的上限,最多存储多少个记录对象
        eternal:代表对象是否永不过期 (指定true则下面两项配置需为0无限期)
        timeToIdleSeconds:最大的发呆时间 /秒
        timeToLiveSeconds:最大的存活时间 /秒
        overflowToDisk:是否允许对象被写入到磁盘
        说明:下列配置自缓存建立起600秒(10分钟)有效 。
        在有效的600秒(10分钟)内,如果连续120秒(2分钟)未访问缓存,则缓存失效。
        就算有访问,也只会存活600秒。
     -->
    <defaultCache maxElementsInMemory="10000" eternal="false"
                  timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="true" />
 
    <cache name="myCache" maxElementsInMemory="10000" eternal="false"
                  timeToIdleSeconds="120" timeToLiveSeconds="600" overflowToDisk="true" />
 
</ehcache>

4.使用缓存

@CacheConfig(cacheNames = {“myCache”})设置ehcache的名称,这个名称必须在ehcache.xml已配置 。

@CacheConfig(cacheNames = {
    
    "myCache"})
public class BotRelationServiceImpl implements BotRelationService {
    
    
 
    @Cacheable(key = "targetClass + methodName +#p0")
    public List<BotRelation> findAllLimit(int num) {
    
    
        return botRelationRepository.findAllLimit(num);
    }
 
}

整合完毕!

别忘了在启动类开启缓存!

六:整合Redis

Redis 优势

性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性

1.启动Redis

下载地址:https://github.com/MicrosoftArchive/redis/releases
这里写图片描述

2.导入依赖

就只需要这一个依赖!不需要spring-boot-starter-cache

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

当你导入这一个依赖时,SpringBoot的CacheManager就会使用RedisCache。

如果你的Redis使用默认配置,这时候已经可以启动程序了。

3.配置Redis

# Redis数据库索引(默认为0)
spring.redis.database=1
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=1000
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=2
# 连接超时时间(毫秒)
spring.redis.timeout=0

4.模板编程

除了使用注解,我们还可以使用Redis模板。
Spring boot集成 Redis 客户端jedis。封装Redis 连接池,以及操作模板。

  @Autowired
    private StringRedisTemplate stringRedisTemplate;//操作key-value都是字符串
 
    @Autowired
    private RedisTemplate redisTemplate;//操作key-value都是对象
 
    /**
     *  Redis常见的五大数据类型:
     *  stringRedisTemplate.opsForValue();[String(字符串)]
     *  stringRedisTemplate.opsForList();[List(列表)]
     *  stringRedisTemplate.opsForSet();[Set(集合)]
     *  stringRedisTemplate.opsForHash();[Hash(散列)]
     *  stringRedisTemplate.opsForZSet();[ZSet(有序集合)]
     */
    public void test(){
    
    
        stringRedisTemplate.opsForValue().append("msg","hello");}

Supongo que te gusta

Origin blog.csdn.net/m0_49353216/article/details/108980324
Recomendado
Clasificación