原理
从Spring3.1开始,Spring框架提供了对Cache的支持,提供了一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的作用。提供的主要注解有@Cacheable、@CachePut、@CacheEvict和@Caching,具体见下表:
注解 | 说明 |
---|---|
@Cacheable | 可以标注在类或方法上:标注在方法上表示该方法支持数据缓存;标在类上表示该类的所有方法都支持数据缓存。 具体功能:在执行方法体之前,检查缓存中是否有相同key值的缓存存在,如果存在对应的缓存,直接返回缓存中的值;如果不存在对应的缓存,则执行相应的方法体获取数据,并将数据存储到缓存中。 |
@CachePut | 可以标注在类或方法上,表示支持数据缓存。 具体功能:在方法执行前不会检查缓存中是否存在相应的缓存,而是每次都会执行方法体,并将方法执行结果存储到缓存中,如果相应key值的缓存存在,则更新key对应的value值。 |
@CacheEvict | 可以标注在类或方法上,用于清除相应key值的缓存。 |
@Caching | 可以标注在类或方法上,它有三个属性cacheable、put、evict分别用于指定@Cacheable、@CachePut和@CacheEvict |
当需要在类上或方法上同时使用多个注解时,可以使用@Caching,如:
@Caching(cacheable=@Cacheable("User"), evict = {@CacheEvict("Member"), @CacheEvict(value = "Customer", allEntries = true)})
@Cacheable的常用属性及说明如下表所示:
@Cacheable属性 | 说明 |
---|---|
key | 表示缓存的名称,必须指定且至少要有一个值,比如:@Cacheable(value=“Dept”)或@Cacheable(value={“Dept”,“Depts”}) |
condition | 表示是否需要缓存,默认为空,表示所有情况都会缓存。通过SpEL表达式来指定,若condition的值为true则会缓存,若为false则不会缓存,如@Cacheable(value=“Dept”,key="‘deptno_’+# deptno “,condition=”#deptno<=40") |
value | 表示缓存的key,支持SpEL表达式,如@Cacheable(value=“Dept”,key="‘deptno_’ +#deptno"),可以不指定值,如果不指定,则缺省按照方法的所有参数进行组合。除了上述使用方法参数作为key之外,Spring还提供了一个root对象用来生成key,使用方法如下表所示,其中"#root"可以省略。 |
Root对象
Root对象 | 说明 |
---|---|
methodName | 当前方法名,比如#root.methodName |
method | 当前方法,比如#root.method.name |
target | 当前被调用的对象,比如#root.target |
targetClass | 当前被调用的对象的class,比如#root.targetClass |
args | 当前方法参数组成的数组,比如#root.args[0] |
caches | 当前被调用的方法使用的缓存,比如#root.caches[0].name |
@CachePut的常用属性同@Cacheable。@CacheEvict的常用属性如下表所示:
@CacheEvict属性 | 说明 |
---|---|
value | 表示要清除的缓存名 |
key | 表示需要清除的缓存key值, |
condition | 当condition的值为true时才清除缓存 |
allEntries | 表示是否需要清除缓存中的所有元素。默认为false,表示不需要,当指定了allEntries为true时,将忽略指定的key。 |
beforeInvocation | 清除操作默认是在方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当该属性值为true时,会在调用该方法之前清除缓存中的指定元素。 |
示例:设置当 dname 的长度大于3时才缓存
//条件缓存
@ResponseBody
@GetMapping("/getLocByDname")
@Cacheable(cacheNames = "dept", key = "#dname", condition = "#dname.length()>3")
public String getLocByDname(@RequestParam("dname") String dname) {//key动态参数
QueryWrapper<Dept> queryMapper = new QueryWrapper<>();
queryMapper.eq("dname", dname);
Dept dept = deptService.getOne(queryMapper);
return dept.getLoc();
}
示例:unless 即条件不成立时缓存。#result 代表返回值,意思是当返回码不等于 200 时不缓存,也就是等于 200 时才缓存。
@ResponseBody
@GetMapping("/getDeptByDname")
@Cacheable(cacheNames = "dept", key = "#dname", unless = "#result.code != 200")
public Result<Dept> getDeptByDname(@RequestParam("dname") String dname){//key动态参数
QueryWrapper<Dept> queryMapper = new QueryWrapper<>();
queryMapper.eq("dname", dname);
Dept dept = deptService.getOne(queryMapper);
if (dept == null)
return ResultUtil.error(120, "dept is null");
else
return ResultUtil.success(dept);
}