Redis(三)org.springframework.cache.annotation下的注解学习

参考博客:

@CachePut、@Cacheable、@CacheEvict

在这里插入图片描述
@CachePut:被修饰的方法需要返回值,通常用于新增、修改操作。执行方法,将方法的执行结果放到缓存中
@Cacheable:被修饰的方法需要返回值,通常用于读操作。有缓存则用缓存;没缓存则执行方法,将方法的执行结果放入缓存。相当于getAndaddCacheIfAbsent
@CacheEvict:方法不需要返回值,通常用于删除操作。执行方法后删除缓存。

其中@CachePut、@Cacheable、@CacheEvict有以下的参数

参数解释example
value/cacheNames缓存的名称
key缓存的key值生成规则。可以为空,缺省时按照方法的所有参数进行组合;如果指定则要按照 SpEL 表达式编写
condition缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存@CacheEvict(value=”testcache”,condition=”#userName.length()>2”)
allEntries(@CacheEvict特有)是否清空所有缓存内容.缺省为 false,如果指定为 true,则方法调用后将立即清空所有cacheNames相同的缓存@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation(@CacheEvict特有)是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存@CachEvict(value=”testcache”,beforeInvocation=true)

redis中真正生成的key值是:cacheNames:key,如下代码

@Cacheable(cacheNames = "car", key = "#id")
@Override
public Car getById(String id) {
    return  = service.getById(id);
}

// 假设有数据:car {id: 1, name: 粤A 00000}
// 如果传入1,则会在redis里缓存 car:1 -> {id: 1, name: 粤A 00000}

缓存的名称,在 spring 配置文件中定义,必须指定至少一个 @CacheEvict(value=”my cache”)
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 @CacheEvict(value=”testcache”,key=”#userName”)
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 @CacheEvict(value=”testcache”,condition=”#userName.length()>2”)
allEntries ,

SPEL表达式

名称位置描述示例
methodNameroot对象当前被调用的方法名root.methodName
methodroot对象当前被调用的方法root.method.name
targetroot对象当前被调用的目标对象root.target
targetClassroot对象当前被调用的目标对象类root.targetClass
argsroot对象当前被调用的方法的参数列表root.args[0]
cachesroot对象当前方法调用使用的缓存列表(如@Cacheable(value={“cache1”, “cache2”})),则有两个cacheroot.caches[0].name
argument name执行上下文当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数user.id
result执行上下文方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,’cache evict’的beforeInvocation=false)result

要注意的点

@Cacheable方法返回null

代码如下所示,当调用者传入不合法的id值,导致查询的结果为null,@Cacheable将方法的执行结果null缓存到redis,这样只要攻击者发大量的这种请求,就可以把redis内存撑爆。

@Cacheable(cacheNames = "car", key = "#id")
@Override
public Car getById(String id) {
    return  = service.getById(id);
}

解决办法

// unless会在方法执行后判断,所以可以获取到result
@Cacheable(cacheNames = "car", key = "#id", unless = "null == #result")
@Override
public Car getById(String id) {
    return = service.getById(id);
}

虽然这样可以防止撑爆redis的内存,但是这样会有大量无效的请求打到数据库。这也就是缓存穿透,缓存穿透会在以后的博客中学习。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫985

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值