简介
平时大家使用redis一般都是直接存储key,value.
spring全家桶肯定帮大家想到了这一点.可以让大家方便的使用注解操作redis节省代码量.
把总结放前面:
总共有三种方式,底层利用了spring的aop,并且方法返回的对象一定要实现序列化
- @Cacheable:注解于方法上,第一次会把后面的cacheNames+key 拼接为key,把返回值序列化后作为value set到redis中去.后面再一次访问相同的key的时候就直接从redis中取值了,不会再访问这个方法
@Override
@Cacheable(cacheNames = "product",key = "#id")
public ProductInfo findOne(String id) {
return productInfoRepository.findById(id).orElse(null);
}
- @CachePut:每次都会把方法的返回值序列化之后set到redis中去(每次都会执行方法),即更新这个key对应的值
@Override
@CachePut(cacheNames = "product",key = "#productId")
public ProductInfo onSale(String productId) {
ProductInfo productInfo = this.findOne(productId);
if(null == productInfo){
throw new SellException(ResultEnum.PRODUCT_NOT_EXIST);
}
if(productInfo.getProductStatusEnum().getCode() == ProductStatusEnum.UP.getCode()){
log.warn("[商品上架处理]-----商品已经是上架状态了,这里直接返回原ProductInfo={}",productInfo);
}else {
productInfo.setProductStatus(ProductStatusEnum.UP.getCode());
productInfo = this.save(productInfo);
}
return productInfo;
}
- @CacheEvict:这个比较好理解,就是从redis中把这个key删除了
@Override
@CacheEvict(cacheNames = "product",key = "#productInfo.productId")
public ProductInfo save(ProductInfo productInfo) {
return productInfoRepository.save(productInfo);
}
这里的key其实可以不写,比如上面的@CacheEvict中不写的话就会把参数默认为key,即下面的productInfo对象
一次驱逐多个redis的key
@Caching(evict={
@CacheEvict(value = Cache.CONSTANT, key = "'" + CacheKey.SINGLE_ROLE_NAME + "'+#roleId"),
@CacheEvict(value = Cache.CONSTANT, key = "'" + CacheKey.ROLES_NAME + "'+#roleId"),
@CacheEvict(value = Cache.CONSTANT, key = "'" + CacheKey.SINGLE_ROLE_NAME + "'+#roleId")
})
public ResponseData remove(@RequestParam Long roleId) {
………………
}
用cacheManager手动put key和value
@Autowired
private CacheManager cacheManager;
...
cacheManager.getCache(PortalConstants.CACHE_PORTAL_MOBILE_VERIFICATION_CODE).put(key, verificationCode);
使用注解前现在启动类中加上@EnableCaching注解
这个注解是spring的,在spring-boot-starter-web包中.一般使用springmvc的都在springboot中引入这个依赖了,所以不用另外引入依赖了.
如果你想单独引入这个依赖的话
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
可以加在方法上使用@Cacheable set value到redis
使用@Cacheable后,第一次会把后面的cacheNames+key 拼接为key,把返回值序列化后作为value set到redis中去.后面再一次访问相同的key的时候就直接从redis中取值了,不会再访问这个方法,也就不会再从数据库中取值了
可以把方法中的参数拼到key上,在这个方法运行完后会把这个方法的返回值根据@Cacheable注解中的cacheNames+key拼接后的值为key,set到redis中取,下次再访问这个key的时候直接从redis中取数据,不用去mysql查找一遍了
redis中缓存的key
使用condition,对传入的参数进行,筛选只允许符合条件的请求set到redis中
对于现实的需求,肯定有些时候是异常请求,是不需要缓存到redis中的,这里我们也可以使用condition加上判断,判断通过的时候才允许缓存到redis
有根据请求筛选,那么自然也就有根据方法的结果筛选的,根据结果筛选可以使用unless
@Cacheable中,unless参数的作用是:函数返回值符合表达式条件的,veto(否决)、不缓存
换句话说,函数返回值符合条件的排除掉、只缓存其余不符合条件的
若是想要某种条件下才缓存,那么可以在el表达式中对其他情况取反就行了
例如,想要返回结果中productId = 1的,那么可以这样写
@Cacheable(cacheNames = “product111”,key = “#productInfo.productId”, unless = “!#result.productId.equals(‘1’)”)
把结果中不等于1的排除掉,那么剩下的就是等于1了
这里可能有点绕,因为unless自动在最外面取了个反,所以要双重否定
简单说就是对你想要的结果取反,unless自己外面有取反!!2个取反就还是原先的结果
@CachePut 更新value到redis
@CachePut和@Cacheable的相同点都可以加在方法上
不同之处在于@CachePut是每次都会把方法的返回值序列化之后set到redis中去(每次都会执行方法),即更新这个key对应的值,适合用于修改值的方法
这里要注意一点参数里的key后面支持spel表达式,可以从下面的方法中获取参数,然后类型和获取的参数的类型是一样的,虽然外面的双引号,但是里面你直接给个数字,它会当成int去处理的,int的话就会有上限2^31 -1
比如,下图中key就为String类型的字符串
而下图中key的值就是int类型的
@CacheEvict 从redis中删除 key
这个也比较好理解,就是从redis中把这个key删除了
这里的key其实可以不写,不写的话就会把参数默认为key,即下面的productInfo对象
使用@CacheConfig注解可以让多个方法使用统一的cacheNames
如果在同一个类中,要使用redis缓存的每个方法中都要写cacheNames是不是觉得很麻烦,可以使用@CacheConfig(cacheNames = “product”),为下面的注解默认使用上面这个CacheConfig中定义的cacheNames
这个和css中的作用域一样,如果方法上的注解有自己定义的cacheNames,那么最后生效的还是方法上自己定义的cacheNames,并不会强行使用类上CacheConfig定义的cacheNames