SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用
在上一篇文章(《SpringBoot(二十四)整合Redis》)中,已经实现了Spring Boot对Redis的整合,既然已经讲到Cache了,今天就介绍介绍缓存注解。各家互联网产品现在数据量越来越大,其快速增长造成网络拥塞和服务器超载,导致客户访问延迟增大,服务质量日益显现出来。缓存技术被认为是减轻服务器负载、降低网络拥塞、增强可扩展性的有效途径之一。
v概念介绍
Spring为我们提供了几个注解来支持Spring Cache。其核心主要是@Cacheable和@CacheEvict。使用@Cacheable标记的方法在执行后Spring Cache将缓存其返回结果,而使用@CacheEvict标记的方法会在方法执行前或者执行后移除Spring Cache中的某些元素。下面我们将来详细介绍一下Spring基于注解对Cache的支持所提供的几个注解。
Spring Cache常见概念介绍
| 名称 | 解释 |
|---|---|
| Cache | 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 |
| CacheManager | 缓存管理器,管理各种缓存(cache)组件 |
| @Cacheable | 主要针对方法配置,能够根据方法的请求参数对其进行缓存 |
| @CacheEvict | 清空缓存 |
| @CachePut | 保证方法被调用,又希望结果被缓存。 与@Cacheable区别在于是否每次都调用方法,常用于更新 |
| @EnableCaching | 开启基于注解的缓存 |
| keyGenerator | 缓存数据时key生成策略 |
| serialize | 缓存数据时value序列化策略 |
| @CacheConfig | 统一配置本类的缓存注解的属性 |
注解(@Cacheable/@CachePut/@CacheEvict)的主要参数
| 名称 | 解释 | example |
|---|---|---|
| value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 | e.g. @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”} |
| key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写, 如果不指定,则缺省按照方法的所有参数进行组合 |
e.g. @Cacheable(value=”testcache”,key=”#id”) |
| condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false, 只有为 true 才进行缓存/清除缓存 |
e.g.@Cacheable(value=”testcache”,condition=”#userName.length()>2”) |
| unless | 否定缓存。当条件结果为TRUE时,就不会缓存。 | e.g.@Cacheable(value=”testcache”,unless=”#userName.length()>2”) |
| allEntries (@CacheEvict ) |
是否清空所有缓存内容,缺省为 false,如果指定为 true, 则方法调用后将立即清空所有缓存 |
e.g. @CachEvict(value=”testcache”,allEntries=true) |
| beforeInvocation (@CacheEvict) |
是否在方法执行前就清空,缺省为 false,如果指定为 true, 则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法 执行抛出异常,则不会清空缓存 |
e.g. @CachEvict(value=”testcache”,beforeInvocation=true) |
v准备工作
1.1 引入依赖pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
激活启动类注解@EnableCaching

v实战演练
2.1 添加service层
package com.demo.service; import com.demo.pojo.UserDetails; /**
* Created by toutou on 2019/1/20.
*/
public interface CacheService {
UserDetails getUserDetailsByUid(int uid); UserDetails updateUserInfo(UserDetails userDetails); int delUserInfoById(int uid);
}
package com.demo.service; import com.demo.dao.UserDetailsMapper;
import com.demo.pojo.UserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; /**
* Created by toutou on 2019/1/20.
*/
@Service
public class CacheServiceImpl implements CacheService{ @Autowired
UserDetailsMapper userDetailsMapper; @Override
@Cacheable(value = "user_details", key = "#uid", unless="#result == null")
public UserDetails getUserDetailsByUid(int uid){
System.out.println(" Cacheable 有请求过来了");
UserDetails userDetails = userDetailsMapper.getUserDetailsByUid(uid);
return userDetails;
} @Override
@CachePut(value = "user_details", key = "#user.id")
public UserDetails updateUserInfo(UserDetails user){
System.out.println(" CachePut 有请求过来了");
if(userDetailsMapper.updateByPrimaryKeySelective(user) > 0) {
// 这里也可以直接在updateByPrimaryKeySelective的方法里,修改后直接查询出该记录返回UserDetails实例,看需求。
user = userDetailsMapper.getUserDetailsByUid(user.getId());
return user;
}else{
return null;
}
} @Override
@CacheEvict(value = "user_details", key = "#uid")
public int delUserInfoById(int uid){
System.out.println(" CacheEvict 有请求过来了");
return userDetailsMapper.deleteByPrimaryKey(uid);
}
}
unless="#result == null"是指当查询为空时,不缓存,默认是空也会缓存。
2.2 添加CacheController
package com.demo.controller; import com.demo.pojo.UserDetails;
import com.demo.service.CacheService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* Created by toutou on 2019/1/20.
*/
@RestController
@Slf4j
public class CacheController { @Autowired
CacheService cacheService; @RequestMapping(value = "/cache/getuserbyid")
public UserDetails getUserDetailsByUid(int uid){
try {
return cacheService.getUserDetailsByUid(uid);
}catch (Exception e){
System.out.println(e.toString());
return null;
}
} @RequestMapping(value = "/cache/updateuserinfo")
public int updateUserInfo(int uid, String city){
UserDetails userDetails = new UserDetails();
userDetails.setId(uid);
userDetails.setCity(city);
userDetails = cacheService.updateUserInfo(userDetails);
return userDetails == null ? 0 : userDetails.getUid();
} @RequestMapping(value = "/cache/deluserinfobyid")
public int delUserInfoById(int uid){
return cacheService.delUserInfoById(uid);
}
}
2.3 实现Serializable接口

v效果展示
3.1 Cacheable效果
当我们本地请求http://localhost:8081/cache/getuserbyid?uid=5接口时,可以看到控制台输出Cacheable 有请求过来了,而后续再次请求该接口时,不会再输出Cacheable 有请求过来了,这是因为直接走了缓存机制了,CacheServiceImpl的方法不再被调用。

通过Redis可以看到,user_details::5的记录已被创建。

3.2 CachePut效果
当我们本地请求http://localhost:8081/cache/updateuserinfo?uid=5&city=首都 接口时,将更新数据库和Redis中对应的字段值。

查询接口,更新成功。控制台再次输出Cacheable 有请求过来了

3.3 CacheEvict效果
当我们本地请求http://localhost:8081/cache/deluserinfobyid?uid=5 接口时,将删除数据中和Redis中的数据。

v博客总结
Redis和@Cacheable、@CachePut、@CacheEvict结合使用,效果挺好,结合这篇和上篇文章(《SpringBoot(二十四)整合Redis》),可以尝试着结合使用试试。
v源码地址
https://github.com/toutouge/javademosecond/tree/master/hellospringboot
作 者:请叫我头头哥
出 处:http://www.cnblogs.com/toutou/
关于作者:专注于基础平台的项目开发。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
SpringBoot进阶教程(二十五)整合Redis之@Cacheable、@CachePut、@CacheEvict的应用的更多相关文章
- SpringBoot进阶教程(二十九)整合Redis 发布订阅
SUBSCRIBE, UNSUBSCRIBE 和 PUBLISH 实现了 发布/订阅消息范例,发送者 (publishers) 不用编程就可以向特定的接受者发送消息 (subscribers). Ra ...
- SpringBoot进阶教程(二十八)整合Redis事物
Redis默认情况下,事务支持被禁用,必须通过设置setEnableTransactionSupport(true)为使用中的每个redistplate显式启用.这样做会强制将当前重新连接绑定到触发m ...
- SpringBoot进阶教程(二十六)整合Redis之共享Session
集群现在越来越常见,当我们项目搭建了集群,就会产生session共享问题.因为session是保存在服务器上面的.那么解决这一问题,大致有三个方案,1.通过nginx的负载均衡其中一种ip绑定来实现( ...
- SpringBoot进阶教程(二十四)整合Redis
缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力.Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓存的场合非 ...
- SpringBoot进阶教程(六十五)自定义注解
在上一篇文章<SpringBoot进阶教程(六十四)注解大全>中介绍了springboot的常用注解,springboot提供的注解非常的多,这些注解简化了我们的很多操作.今天主要介绍介绍 ...
- SpringBoot进阶教程(七十四)整合ELK
在上一篇文章<SpringBoot进阶教程(七十三)整合elasticsearch >,已经详细介绍了关于elasticsearch的安装与使用,现在主要来看看关于ELK的定义.安装及使用 ...
- SpringBoot进阶教程(二十二)集成RabbitMQ---MQ实战演练
RabbitMQ是一个在AMQP基础上完成的,可复用的企业消息系统.他遵循Mozilla Public License开源协议.RabbitMQ是流行的开源消息队列系统,用erlang语言开发.Rab ...
- SpringBoot进阶教程(二十七)整合Redis之分布式锁
在之前的一篇文章(<Java分布式锁,搞懂分布式锁实现看这篇文章就对了>),已经介绍过几种java分布式锁,今天来个Redis分布式锁的demo.redis 现在已经成为系统缓存的必备组件 ...
- SpringBoot进阶教程(六十四)注解大全
在Spring1.x时代,还没出现注解,需要大量xml配置文件并在内部编写大量bean标签.Java5推出新特性annotation,为spring的更新奠定了基础.从Spring 2.X开始spri ...
随机推荐
- 微信小程序录音实现
最近在写一个小程序的功能,需求是需要把用户的录音记录并上传到服务器,然后调用接口来实现播放功能. 翻阅不少资料都发现小程序对wx.startRecord()接口不在维护, 注意:1.6.0 版本开始, ...
- 完全关闭Hyper-v的方法
众所周知Hyper-v和vmware有冲突,开启Hyper-v功能vmware就不能使用,但即使关闭了也是如此,这是因为功能没有被完全关闭,这里整理下方法,我自己在两台机子亲测有效. win+x,a, ...
- 8.Vue基础
环境搭建 node.js安装 https://nodejs.org/en/ cnpm npm install -g cnpm --registry=https://registry.npm.taoba ...
- django自定义用户表
django中已经给我生成默认的User表,其中的字段已经可以满足我们的日常需求. 但有时候,我们需要更多的字段,我们就可以自定义.来替换django自带的User表. #models.py from ...
- django优化和扩展(一)
mysql优化基础 进行django产品开发或上线之前,有必要了解一下mysql的基础知识,orm太过抽象,导致很多朋友对于mysql了解得太少,而且orm不像sqlalchemy那样可以跟mysql ...
- struts升级2.3.12到2.5.13
参考文章: http://www.ituring.com.cn/article/495914 http://blog.csdn.net/zhangchen1987/article/details/78 ...
- iscsi 挂载网络存储及存储访问
http://blog.sina.com.cn/s/blog_408764940101ghzi.html 一.Ess3016x设置 登陆admin 密码 888888888888 1.安装硬盘,查看硬 ...
- 格子刷油漆【动态规划问题】—NYOJ 980
个人博客页:https://www.scriptboy.cn/198.html 出处:蓝桥杯 题目描述: X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护 ...
- 分布式架构真正适用于大型互联网项目的架构! dubbo+zookeeper+springmvc+mybatis+shiro+redis
分类: 分布式技术(3) 目录(?)[+] 平台简介 Jeesz是一个分布式的框架,提供项目模块化.服务化.热插拔的思想,高度封装安全性的Java EE快速开发平台. Jeesz本身集成D ...
- spring中@Resource和@Autowired理解
一.@Resource的理解 @Resource在bean注入的时候使用,@Resource所属包其实不是spring,而是javax.annotation.Resource,只不过spring支持该 ...