springboot-mybatis-plus 整合Ehcache开启二级缓存
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
Ehcache最初是由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然是开源,但一些新的主要功能(例如,快速可重启性之间的一致性的)只能在商业产品中使用,例如Enterprise EHCache and BigMemory。维基媒体Foundationannounced目前使用的就是Ehcache技术。
主要的特性有:
1. 快速
2. 简单
3. 多种缓存策略
4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题
5. 缓存数据会在虚拟机重启的过程中写入磁盘
6. 可以通过RMI、可插入API等方式进行分布式缓存
7. 具有缓存和缓存管理器的侦听接口
8. 支持多缓存管理器实例,以及一个实例的多个缓存区域
9. 提供Hibernate的缓存实现
----百度百科
1.新建一个springboot 项目 在我们的pom.xml 文件中添加如下配置
<!-- mybatisPlus 核心库 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <!-- 开启二级缓存 --> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.1.0</version> </dependency>
2. 在我们的配置文件中开启mybatis的二级缓存 并配置ehcache.xml 文件路径
mybatis-plus.configuration.cache-enabled=true
spring.cache.ehcache.config=classpath:/ehcache.xml
3.新建 ehcache.xml 文件 文件的路径 src/main/resources/ehcache.xml
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">
<!-- 磁盘缓存位置
path属性可以配置的目录有:
user.home(用户的家目录)
user.dir(用户当前的工作目录)
java.io.tmpdir(默认的临时目录)
ehcache.disk.store.dir(ehcache的配置目录)
绝对路径(如:d:\\ehcache)
-->
<diskStore path="java.io.tmpdir" />
<!--
name:缓存名称。
maxElementsInMemory:缓存最大个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
maxElementsOnDisk:硬盘最大缓存个数。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
-->
<!-- 默认缓存 -->
<defaultCache
eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU" />
<!-- 自定义缓存 -->
<cache
name="MyCache"
eternal="false"
maxElementsInMemory="1000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="5"
timeToLiveSeconds="5"
memoryStoreEvictionPolicy="LRU" />
</ehcache>
4.在我们的mapper文件中 添加如下配置
<cache type="org.mybatis.caches.ehcache.EhcacheCache"> <property name="timeToIdleSeconds" value="3600"/> <property name="timeToLiveSeconds" value="3600"/> <property name="maxEntriesLocalHeap" value="1000"/> <property name="maxEntriesLocalDisk" value="10000000"/> <property name="memoryStoreEvictionPolicy" value="LRU"/> </cache>
新建一个controller 测试 初次查询访问数据库
再次点击查询 可以看到并未访问数据库 结果依旧返回了
现在测试当我更新数据后 是否会重新查询数据库 执行修改方法
修改数据库 再次点击查询 并未走缓存 而是直接去查询数据库
在这里有个问题 我使用的更新方法是我自己写的mapper 在xml文件中有sql,mybatis-plus 自己生成的一系列方法 并未进入缓存
如有解决方案请 联系我
新建测试方法来打印cache缓存的数据 在网上查询到有 ehcache-monitor 管理工具 但是我并未找到对应的文件
这面我还是用代码来打印数据
CacheManager manager = CacheManager.create(this.getClass().getClassLoader().getResourceAsStream("classpath:ehcache.xml")); DateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String[] cacheNames = manager.getCacheNames(); System.out.println("读取的缓存列表为:"); for (int i = 0; i < cacheNames.length; i++) { Cache cache = manager.getCache(cacheNames[i]); System.out.println("--" + (i + 1) + " " + cacheNames[i]); //缓存元素集合 System.out.println("-----------------------缓存元素统计数据---------------------------------"); List keys = cache.getKeys(); for (Object key : keys) { Element ele = cache.get(key); System.out.println("内容: " + ele.getValue()); System.out.println("创建时间: " + sf.format(ele.getCreationTime())); System.out.println("最后访问时间: " + sf.format(ele.getLastAccessTime())); System.out.println("过期时间: " + sf.format(ele.getExpirationTime())); System.out.println("最后更新时间: " + sf.format(ele.getLastUpdateTime())); System.out.println("命中次数: " + ele.getHitCount()); System.out.println("存活时间: " + ele.getTimeToLive() + "ms"); System.out.println("空闲时间: " + ele.getTimeToIdle() + "ms"); } System.out.println("--------------------------------------------------------"); System.out.println("-----------------------缓存总统计数据---------------------------------"); long elementsInMemory1 = cache.getMemoryStoreSize(); System.out.println("得到缓存对象占用内存的数量:" + elementsInMemory1); long elementsInMemory2 = cache.getDiskStoreSize(); System.out.println("得到缓存对对象占用磁盘的数量:" + elementsInMemory2); //获取缓存统计对象 Statistics stat = cache.getStatistics(); long hits = stat.getCacheHits(); System.out.println("得到缓存读取的命中次数:" + hits); long memoryHits = stat.getInMemoryHits(); System.out.println("得到内存中缓存读取的命中次数:" + memoryHits); long diskHits = stat.getOnDiskHits(); System.out.println("得到磁盘中缓存读取的命中次数:" + diskHits); long cacheMisses = stat.getCacheMisses(); System.out.println("得到缓存读取的丢失次数:" + cacheMisses); long evictionCount = stat.getEvictionCount(); System.out.println("得到缓存读取的已经被销毁的对象丢失次数:" + evictionCount); System.out.println("--------------------------------------------------------"); }
控制台的输出为
读取的缓存列表为: --1 MyCache -----------------------缓存元素统计数据--------------------------------- -------------------------------------------------------- -----------------------缓存总统计数据--------------------------------- 得到缓存对象占用内存的数量:0 得到缓存对对象占用磁盘的数量:0 得到缓存读取的命中次数:0 得到内存中缓存读取的命中次数:0 得到磁盘中缓存读取的命中次数:0 得到缓存读取的丢失次数:0 得到缓存读取的已经被销毁的对象丢失次数:0 -------------------------------------------------------- --2 com.demonlover.wx.auth.mapper.ContentMapper -----------------------缓存元素统计数据--------------------------------- 内容: [Content(id=28, categoryId=89, title=标题, subTitle=子标题, titleDesc=标题说明, url=http://www.jd.com, pic=, pic2=, content=, created=Sun Apr 07 13:56:09 CST 2019, updated=Sun Apr 07 13:56:11 CST 2019)] 创建时间: 2020-06-24 16:04:55 最后访问时间: 2020-06-24 16:04:57 过期时间: 2020-06-24 17:04:55 最后更新时间: 2020-06-24 16:04:55 命中次数: 1 存活时间: 3600ms 空闲时间: 3600ms -------------------------------------------------------- -----------------------缓存总统计数据--------------------------------- 得到缓存对象占用内存的数量:1 得到缓存对对象占用磁盘的数量:0 得到缓存读取的命中次数:0 得到内存中缓存读取的命中次数:0 得到磁盘中缓存读取的命中次数:0 得到缓存读取的丢失次数:0 得到缓存读取的已经被销毁的对象丢失次数:0 --------------------------------------------------------