前言

  日常开发中,缓存是解决数据库压力的一种方案,通常用于频繁查询的数据,例如新闻中的热点新闻,本文记录springboot中使用cache缓存。

  官方文档介绍:https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-caching-provider-generic

  

  工程结构

  代码编写

  pom引入依赖,引入cache缓存,数据库使用mysql,ORM框架用jpa

        <!--添加springdata-cache依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency> <!-- 引入ehcache支持 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency> <!--添加springdata-jpa依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> <!--添加MySQL驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

  配置文件

server.port=10010
spring.application.name=springboot-cache spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:/ehcache.xml

  ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <!-- 磁盘缓存位置 -->
<diskStore path="java.io.tmpdir"/> <!-- maxEntriesLocalHeap:堆内存中最大缓存对象数,0没有限制 -->
<!-- maxElementsInMemory: 在内存中缓存的element的最大数目。-->
<!-- eternal:elements是否永久有效,如果为true,timeouts将被忽略,element将永不过期 -->
<!-- timeToIdleSeconds:发呆秒数,发呆期间未访问缓存立即过期,当eternal为false时,这个属性才有效,0为不限制 -->
<!-- timeToLiveSeconds:总存活秒数,当eternal为false时,这个属性才有效,0为不限制 -->
<!-- overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上 -->
<!-- statistics:是否收集统计信息。如果需要监控缓存使用情况,应该打开这个选项。默认为关闭(统计会影响性能)。设置statistics="true"开启统计 --> <!--
默认缓存
无过期时间,但 600 秒内无人访问缓存立即过期
-->
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="0"
overflowToDisk="false">
</defaultCache> <!--
xx业务缓存
在有效的 120 秒内,如果连续 60 秒未访问缓存,则缓存失效。
就算有访问,也只会存活 120 秒。
-->
<cache name="myCache"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="0"
overflowToDisk="false">
</cache>
</ehcache>

  先写一个套tb_user表的CRUD代码

@RestController
@RequestMapping("/tbUser/")
public class TbUserController {
@Autowired
private TbUserService tbUserService; //方便测试暂时改成GetMapping
@GetMapping("list")
// @PostMapping("list")
public List<TbUser> list(TbUser entityVo) {
return tbUserService.list(entityVo);
} @GetMapping("get/{id}")
public TbUser get(@PathVariable("id")Integer id) {
return tbUserService.get(id);
} //方便测试暂时改成GetMapping
@GetMapping("save")
// @PostMapping("save")
public TbUser save(TbUser entityVo) {
return tbUserService.save(entityVo);
} @GetMapping("delete/{id}")
public Integer delete( @PathVariable("id") Integer id) {
return tbUserService.delete(id);
}
}

  opjo实体类要实现序列化

@Entity
@Table(name = "tb_user")
@Data
public class TbUser implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;//表id private String username;//用户名 private String password;//密码 private Date created;//创建时间 private Integer descriptionId;//关联详情id
}

  serviceImpl中,使用注解来开启缓存

@Service
@Transactional
@CacheConfig(cacheNames = {"myCache"})
public class TbUserServiceImpl implements TbUserService{ @PersistenceContext
private EntityManager em; @Autowired
private TbUserRepository tbUserRepository; //@Cacheable缓存数据:key为userList,value为返回值List<TbUser>
@Cacheable(key = "'userList'")
@Override
public List<TbUser> list(TbUser entityVo) {
System.out.println("获取list用户列表缓存数据,"+new Date());
return tbUserRepository.findAll(Example.of(entityVo));
} //@Cacheable缓存数据:key为参数id,value为返回值TbUser
@Cacheable(key = "#id")
@Override
public TbUser get(Integer id) {
System.out.println("获取数据缓存,key:"+id);
Optional<TbUser> optionalE = tbUserRepository.findById(id);
if (!optionalE.isPresent()) {
throw new RuntimeException("ID不存在!");
}
return optionalE.get();
} //@CachePut缓存新增的或更新的数据到缓存,其中缓存的名称为people,数据的key是person的id
@CachePut(key = "#entityVo.id")
// @CacheEvict从缓存中删除key为参数userList的数据
@CacheEvict(key = "'userList'")
@Override
public TbUser save(TbUser entityVo) {
System.out.println("新增/更新缓存,key:"+entityVo.getId());
//entityVo传啥存啥,会全部更新
return tbUserRepository.save(entityVo);
} //清空所有缓存
@CacheEvict(allEntries=true)
@Override
public Integer delete(Integer id) {
System.out.println("清空所有缓存");
tbUserRepository.deleteById(id);
return id;
}
}

  效果演示

  http://localhost:10010/tbUser/save?id=2&username=李四

  调用save方法,key为2,value为当前tbUser对象的数据被缓存下来

  

  http://localhost:10010/tbUser/get/2

  当我们调用get方法时,直接获取缓存数据,控制台啥也不打印,连serviceImpl的get方法都不进去(可以打断点调试)

  

  http://localhost:10010/tbUser/save?id=2&username=王五

  当我们再次调用save方法更新username时,缓存数据也被更新

  http://localhost:10010/tbUser/get/2

  再次调用get接口,直接返回缓存数据,后台也是方法都不进去,啥也不打印

  http://localhost:10010/tbUser/delete/2

  调用delete接口,删除数据,同时删除缓存

  再次调用get接口,发现缓存数据被清除,查询数据库

  http://localhost:10010/tbUser/list

  首次调用list接口,key为userList的,value为用户集合数据被缓存下来,再次调用直接返回缓存数据

  当调用save接口,数据更新,删除key为userList的缓存,再次调用list时,重新查库并设置缓存

  我们配置了缓存发呆时间,当120秒内未使用该缓存,立即过期,一直用就会一直存在

  我们先同时访问两个接口list、get,list接口2分钟后再次访问,get接口不能超过2分钟是不是访问一下,结果如预期

  PS:原先使用了这个jar包,有报错

    <dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.8.1</version>
</dependency>

  后面改成用上面“代码编写”里pom中引的jnet.sf.ehcache下面的ar

  后记

  缓存除了能缓解数据库压力,还能做用户登录状态控制,例如:用户登录成功后cookie中保存颁发的token令牌设置永不过期,缓存存活时间也设置永不过期,发呆时间设置1天,这样只有用户在1天内有访问缓存接口,那他就可以一直保留登录状态,直至有其他业务将token或者缓存清掉。

  springboot使用cache缓存暂时先记录到这,后续有空再进行补充。

  代码开源

  代码已经开源、托管到我的GitHub、码云:

  GitHub:https://github.com/huanzi-qch/springBoot

  码云:https://gitee.com/huanzi-qch/springBoot

SpringBoot系列——cache缓存的更多相关文章

  1. SpringBoot日记——Cache缓存篇

    通常我们访问数据的情况如下图,数据存缓存就取缓存,不存缓存就取数据库,这样可以提升效率,不用一直读取数据库的信息: 开始记录: 关于SpringBoot缓存的应用 1. 首先在pom.xml文件中添加 ...

  2. springboot(九) Cache缓存和Redis缓存

    1. Cache缓存 1.1 缓存的概念&缓存注解 Cache 缓存接口,定义缓存操作.实现有:RedisCache.EhCacheCache.ConcurrentMapCache等 Cach ...

  3. SpringBoot系列之缓存使用教程

    介绍SpringBoot项目中使用缓存,之前先介绍一下Spring的缓存抽象和JSR107,本博客是我在学习尚硅谷视频和参考其它博客之后做的笔记,仅供学习参考 @ 目录 一.Spring的缓存抽象 1 ...

  4. 深度理解springboot集成cache缓存之源码解析

    一.案例准备 1.创建数据表(employee表) 2.创建Employee实体类封装数据库中的数据 @AllArgsConstructor @NoArgsConstructor @Data @ToS ...

  5. Springboot使用ehcache缓存

    本文部分步骤继承于springboot使用cache缓存,如果有不清楚的,请移驾springboot使用cache缓存 ehcache是一种广泛使用的开源Java分布式缓存.主要面向通用缓存,Java ...

  6. SpringBoot系列:Spring Boot集成Spring Cache,使用EhCache

    前面的章节,讲解了Spring Boot集成Spring Cache,Spring Cache已经完成了多种Cache的实现,包括EhCache.RedisCache.ConcurrentMapCac ...

  7. Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)

    Ajax跨域问题及解决方案   目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...

  8. springboot系列:使用缓存

    前言:springboot已经为我们实现了抽象的api接口,因此当我们使用不同的缓存时,只是配置有可能有点区别(比如ehcache和Redis),但是在程序中使用缓存的方法是一样的. 1.spring ...

  9. 【快学SpringBoot】快速上手好用方便的Spring Cache缓存框架

    前言 缓存,在开发中是非常常用的.在高并发系统中,如果没有缓存,纯靠数据库来扛,那么数据库压力会非常大,搞不好还会出现宕机的情况.本篇文章,将会带大家学习Spring Cache缓存框架. 原创声明 ...

随机推荐

  1. Python脚本暴力破解FTP口令(ftplib)

    目录 判断FTP服务器是否允许匿名登录 暴力破解FTP口令 列出FTP目录内的网页文件 综合 环境:Windows python2.7.15 ftplib模块是python下用于ftp服务的模块 . ...

  2. windows-DLL注入

    DLL注入     刚刚整理的代码注入(远程线程注入)现在整理这个DLL注入,DLL注入比较常用,相比远程代码注入DLL注入没有什么太多的限制,而且实现起来比较简单,当然远程线程需要注意的问题DLL很 ...

  3. linux当前运行进程

    一:linux查询服务器服务进程 inux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照, 就是执行ps命令的那个时刻的 ...

  4. <JVM上篇:内存与垃圾回收篇>04-虚拟机栈

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  5. layui框架下如何给select的option选项赋值

    后端返回数据格式 axios方法执行成功后返回的数据格式如下图 前端下拉框 <div class="layui-form-item"> <label class= ...

  6. 【maven】理论知识

    Maven是跨平台的项目管理工具,主要服务于Java平台的项目构建.依赖管理. 项目构建 项目构建过程包括[清理项目]→[编译项目]→[测试项目]→[生成测试报告]→[打包项目]→[部署项目]这几个步 ...

  7. Sublime text3 的破解

    下载sublimeText3的安装包并安装(已经安装的可以忽略) 在hosts文件中添加:127.0.0.1 license.sublimehq.com(hosts文件地址:C:\Windows\Sy ...

  8. PHP + JQuery 实现多图上传并预览

    简述 PHP + JQuery实现 前台:将图片进行base64编码,使用ajax实现上传 后台:将base64进行解码,存储至文件夹,将文件名称入库 效果图 功能实现 html <!DOCTY ...

  9. 在局域网内知道计算机的名字查找计算机的IP

    第一步 nbtstat -a 计算机名字 第二步 nbtstat -c 可以看到计算机地址

  10. 【BUAA软工】Beta阶段事后分析

    设想与目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 解决的问题 总体解决的问题:新手编程者配置编程环境难.本地编写的代码跨设备同步难.本地ide安装使用过程 ...