在很多应用场景中通常是获取前后相同或更新不频繁的数据,比如访问产品信息数据、网页数据。如果没有使用缓存,则访问每次需要重复请求数据库,这会导致大部分时间都耗费在数据库查询和方法调用上,因为数据库进行I/O操作非常耗费时间,这时就可以利用Spring Cache来解决。
Spring Cache 是Spring提供的一整套缓存解决方案。它本身并不提供缓存实现,而是提供统一的接口和代码规范、配置、注解等,以便整合各种Cache方案,使用户不用关心Cache的细节。
Spring支持“透明”地向应用程序添加缓存,将缓存应用于方法,在方法执行前检查缓存中是否有可用的数据。这样可以减少方法执行的次数,同时提高响应的速度。缓存的应用方法“透明”,不会对调用者造成任何干扰。只要通过注解@EnableCaching 启用了缓存支持,SpringBoot就会自动处理好缓存的基础配置。
Spring Cache作用在方法上。当调用一个缓存方法时,会把方法参数和返回结果作为一个“键值对”(key/value)存放在缓存中,下次用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache时,要保证在缓存的方法和方法参数相同时返回相同的结果。
Spring Boot 提供的声明式缓存(cache)注解,见表11-1。
注解 | 说明 |
---|---|
@EnableCaching | 开启缓存 |
@Cacheable | 可以作用在类和方法上,以键值对的方式缓存类或方法的返回值 |
@CachePut | 方法被调用,然后结果被缓存 |
@CacheEvict | 清空缓存 |
@Caching | 用来组合多个注解标签 |
标注在入口类上,用于开启缓存。
可以作用在类和方法上,以键值对的方式缓存类或方法的返回值。键可以有默认策略和自定义策略。
@Cacheable 注解会先查询是否已经有缓存,如果已有则会使用缓存,如果没有则会执行方法并进行缓存。
@Cacheable可以指定3个属性——value、key和condition。
@Cacheable注解的使用方法见以下代码:
@Cacheable(value="emp",key="targetClass + methodName + #p0")
public User findUserById(long id){
return userRepository.findById(id);
}
代码解释如下。
@CachePut标注的方法在执行前不检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。和@Cacheable不同的是,@CachePut每次都会触发真实方法的调用,比如用户更新缓存数据。
需要注意的是,该注解的value和key必须与要更新的缓存相同,即与@Cacheable相同。具体见下面两段代码:
@CachePut(value="usr",key="targetClass + #p0")
public User updata(User user){
//省略
}
@Cacheable(value="usr",key="targetClass + #p0")
public User save(User user){
//省略
}
@CacheEvict用来标注需要清除缓存元素的方法或类。该注解用于触发缓存的清除操作。其属性有value、key、condition、allEntries和beforeInvocation。可以用这些属性来指定清除的条件。使用方法如下:
@Cacheable(value="usr",key="#p0.id")
public User save(User user){
//省略
}
//清除一条缓存
@CacheEvict(value="usr",key="#id")
public void deleteByKey(int id){
//省略
}
//在方法调用后清空所有缓存
@CacheEvict(value="accountCache",allEntries=true)
public void deleteAll(){
//省略
}
//在方法调用前清空所有缓存
@CacheEvict(value="accountCache",beforeInvocation=true)
public void deleteAll(){
//省略
}
注解@Caching用来组合多个注解标签,有3个属性:cacheable、put和evict,用于指定@Cacheable、@CachePut和CacheEvict。使用方法如下:
@Caching(cacheable={
@Cacheable(value="usr",key="#p0"),
//省略
},put={
@CachePut(value="usr",key="#p0"),
//省略
},evict={
@CacheEvict(value="usr",key="#p0"),
//省略
})
public User save(User user){
//省略
}
本实例展示Spring Cache是如何使用简单缓存(SIMPLE方式)进行缓存管理的。
要想集成Spring Cache, 只需要在pom.xml文件中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
在application.properties文件中配置目标缓存管理器,支持Ehcache、Generic、Redis、Jcache等。这里使用SIMPLE方式“spring.cache.type=SIMPLE”。
在入口添加注解@EnableCaching,开启缓存功能。
Redis有5种数据类型,见表。
数据类型 | 存储的值 | 读写能力 |
---|---|---|
string(字符串) | 可以是字符串、整数或浮点数 | 对整个字符串或字符串的其中一部分执行操作,对对线和浮点数执行自增(increment)或自减(decrement)操作 |
list(列表) | 一个链表,链表上的每个节点都包含了一个字符串 | 从链表的两端推入或弹出元素;根据偏移量对链表进行修剪(trim);读取单个或多个元素;根据值来查找或移除元素 |
set(集合) | 包含字符串的无序收集器(unorderedcollection),并且被包含的每个字符串都是独一无二的,各不相同 | 添加、获取、移除单个元素;检查一个元素是否存在于某个集合中;计算交集、并集、差集;从集合里随机获取元素 |
hash(散列) | 包含键值对的无序散列表 | 添加、获取、移除单个键值对;获取所有键值对 |
zset(有序集合,sorted set) | 字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定 | 添加、获取、删除单个元素;根据分值范围(range)或成员来获取元素 |