<dependency>
<groupId>org.ehcachegroupId>
<artifactId>ehcacheartifactId>
<version>3.8.1version>
<exclusions>
<exclusion>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-reload4jartifactId>
<version>2.0.6version>
dependency>
官方文档地址:Ehcache 3.8_Getting Started
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
/**
* @author CQY
* @version 1.0
* @date 2023/2/18 11:46
* @desc Ehcache 3.8 java代码配置
**/
public class EhCache38TestJava01 {
public static void main(String[] args) {
try (CacheManager cacheManager =
// 1.静态方法org.ehcache.config.builders.CacheManagerBuilder.newCacheManagerBuilder返回一个新org.ehcache.config.builders.CacheManagerBuilder实例。
CacheManagerBuilder.newCacheManagerBuilder()
/*2. 使用构建器定义Cache别名为“preConfigured”的。cacheManager.build()当在实际实例上调用时将创建此缓存CacheManager。
第一个String参数是缓存别名,用于从CacheManager. 第二个参数org.ehcache.config.CacheConfiguration,用于配置Cache.
我们使用静态newCacheConfigurationBuilder()方法来org.ehcache.config.builders.CacheConfigurationBuilder创建默认配置。
*/
.withCache("preConfigured", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)))
// 3. 调用build()返回一个完全实例化但未初始化的,CacheManager我们可以使用。=> CacheManager使用初始化build(true)。
.build()) {
/*
4. 在使用之前CacheManager需要对其进行初始化,这可以通过以下两种方式之一完成:调用CacheManager.init()实例CacheManager,
或调用CacheManagerBuilder.build(boolean init)布尔参数设置为 true 的方法。
*/
cacheManager.init();
/*
5. 通过将别名、键类型和值类型传递给CacheManager. 例如,要获取在步骤 2 中声明的缓存,
您需要它的alias="preConfigured",keyType=Long.class和valueType=String.class。为了类型安全,我们要求传入键和值类型。如果它们与我们期望的不同,
则会在应用程序生命周期的早期CacheManager抛出。ClassCastException这可以防止Cache被随机类型污染。
*/
Cache<Long, String> preConfigured =
cacheManager.getCache("preConfigured", Long.class, String.class);
/*
6. 可用于根据需要CacheManager创建新实例。Cache正如在第 2 步中一样,它需要传入一个别名和一个CacheConfiguration.
实例化和完全初始化的Cache添加将通过 API 返回和/或访问CacheManager.getCache。
*/
Cache<Long, String> myCache = cacheManager.createCache("myCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder.heap(10)));
/*
7. 新添加的Cache现在可用于存储由键值对组成的条目。put 方法的第一个参数是键,第二个参数是值。
请记住,键和值类型必须与CacheConfiguration. 此外,键必须是唯一的,并且只与一个值相关联。
*/
myCache.put(1L, "da one!");
/*
8. 通过调用该方法从缓存中检索值cache.get(key)。它只接受一个参数,即键,并返回与该键关联的值。如果没有与该键关联的值,则返回 null。
*/
String value = myCache.get(1L);
System.out.println("value:" + value);
/*
9.我们可以CacheManager.removeCache(String)给定Cache。不仅CacheManager会删除它对 的引用 Cache,还会将其关闭。
释放Cache所有本地持有的临时资源(例如内存)。对此的引用Cache变得不可用。
*/
cacheManager.removeCache("preConfigured");
/*
10.为了释放 aCacheManager提供给Cache它管理的实例的所有临时资源(内存、线程……),
您必须调用CacheManager.close(),这又会关闭Cache当时已知的所有实例。
> CacheManager实现Closeable可以通过 try-with-resources 自动关闭。
*/
// cacheManager.close();
}
}
}
<config
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core.xsd">
<cache alias="foo">
<key-type>java.lang.Stringkey-type>
<value-type>java.lang.Stringvalue-type>
<resources>
<heap unit="entries">20heap>
<offheap unit="MB">10offheap>
resources>
cache>
<cache-template name="myDefaults">
<key-type>java.lang.Longkey-type>
<value-type>java.lang.Stringvalue-type>
<heap unit="entries">200heap>
cache-template>
<cache alias="bar" uses-template="myDefaults">
<key-type>java.lang.Numberkey-type>
cache>
<cache alias="simpleCache" uses-template="myDefaults"/>
config>
import cn.hutool.core.io.resource.ResourceUtil;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.Configuration;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.xml.XmlConfiguration;
import java.net.URL;
/**
* @author CQY
* @version 1.0
* @date 2023/2/18 11:46
* @desc Ehcache 3.8 xmlj配置
**/
public class EhCache38TestXml01 {
public static void main(String[] args) {
CacheManager myCacheManager = null;
try {
// hutool工具包获取类路径下的配置文件路径URL
URL url = ResourceUtil.getResource("ehcache.xml");
Configuration xmlConfig = new XmlConfiguration(url);
myCacheManager = CacheManagerBuilder.newCacheManager(xmlConfig);
myCacheManager.init();
Cache<String, String> fooCache = myCacheManager.getCache("foo", String.class, String.class);
fooCache.put("key1", "ABC");
String value1 = fooCache.get("key1");
System.out.println("value1:" + value1);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (myCacheManager != null) {
myCacheManager.close();
}
}
}
}
分层缓存官方文件地址:Tiering options
package pub.qingyun.ehcache;
import cn.hutool.system.SystemUtil;
import lombok.extern.slf4j.Slf4j;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.PersistentCacheManager;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.impl.config.store.disk.OffHeapDiskStoreConfiguration;
import org.junit.Test;
import java.io.File;
import java.time.Duration;
/**
* @author CQY
* @version 1.0
* @date 2023/2/18 12:24
* @desc Ehcache分层缓存
* @see 分层缓存
**/
@Slf4j
public class EhcacheTieringOptionsTestDemo {
/**
* 单层设置-堆
*/
@Test
public void test01() {
// 堆上只允许 10 个条目。驱逐将在满时发生。
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, EntryUnit.ENTRIES);
// or 指定10个条目的快捷方法。
ResourcePoolsBuilder.heap(10);
// or 只允许 10 MB。驱逐将在满时发生。
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10, MemoryUnit.MB);
}
/**
* 单层设置-字节大小的堆
* 对于除堆层之外的每一层,计算缓存的大小都相当容易。您或多或少地总结了包含序列化条目的所有字节缓冲区的大小。
*
* 当堆受大小而不是条目限制时,它有点复杂
*/
@Test
public void test02() {
CacheConfiguration<Long, String> usesConfiguredInCacheConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
// 限制堆层用于存储键值对的内存量。调整对象大小会产生成本。
.heap(10, MemoryUnit.KB)
// 设置仅供堆层使用。所以堆外根本不会使用它。
.offheap(10, MemoryUnit.MB))
.withSizeOfMaxObjectGraph(1000)
/*
大小也可以通过 2 个额外的配置设置进一步限制:第一个指定遍历对象图时要遍历的最大对象数(默认值:),
第二个1000定义单个对象的最大大小(默认值Long.MAX_VALUE:无穷)。如果大小超过这两个限制中的任何一个,条目将不会存储在缓存中。
*/
.withSizeOfMaxObjectSize(1000, MemoryUnit.B)
.build();
CacheConfiguration<Long, String> usesDefaultSizeOfEngineConfig = CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(10, MemoryUnit.KB))
.build();
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.withDefaultSizeOfMaxObjectSize(500, MemoryUnit.B)
.withDefaultSizeOfMaxObjectGraph(2000)
.withCache("usesConfiguredInCache", usesConfiguredInCacheConfig)
.withCache("usesDefaultSizeOfEngine", usesDefaultSizeOfEngineConfig)
.build(true);
}
/**
* 单层设置-堆外层
*
* 存储在堆外的数据必须进行序列化和反序列化——因此比堆慢。
* 因此,您应该支持堆外处理大量数据,而堆内处理会对垃圾收集产生过于严重的影响。
* -XX:MaxDirectMemorySize不要忘记根据您打算使用的堆外大小在 java options 中定义选项。
*/
@Test
public void test03() {
// 堆外只允许 10 MB。驱逐将在满时发生。
ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(10, MemoryUnit.MB);
}
/**
* 单层设置-磁盘层
* 对于磁盘层,数据存储在磁盘上。磁盘越快、越专用,访问数据的速度就越快。
*
* 储在磁盘上的数据必须被序列化/反序列化并写入磁盘/从磁盘读取 - 因此比堆和堆外数据慢
*/
@Test
public void test04() {
try (PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
// 提供应存储数据的位置。
.with(CacheManagerBuilder.persistence(new File(SystemUtil.get("java.io.tmpdir"), "myData")))
.withCache("persistent-cache", CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
// 为缓存将使用的磁盘定义资源池。第三个参数是一个布尔值,用于设置磁盘池是否持久化。当设置为 true 时,池是持久的。
// 当使用带有 2 个参数的版本时disk(long, MemoryUnit),池不是持久的。
ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.MB, true))
// 定义一个OffHeapDiskStoreConfiguration指定所需段数的实例。磁盘存储被分成多个段,这些段提供并发访问,但也保存打开的文件指针。默认值为 16。
.withService(new OffHeapDiskStoreConfiguration(2))
)
.build(true)) {
Cache<Long, String> cache = persistentCacheManager.getCache("persistent-cache", Long.class, String.class);
// 将缓存持久化到硬盘中:C:\Users\*\AppData\Local\Temp\myData\file\threeTieredCache_99af5c58e82ee31980edbfc01dc4f362f30574b4
cache.put(1L, "stillAvailableAfterRestart");
// 存储在缓存中的所有值将在 JVM 重新启动后可用
log.info("key=[{}],value=[{}]", 1L, cache.get(1L));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 多层设置
* 1.多层设置中必须始终有一个堆层。
* 2.您不能组合磁盘层和集群层。
* 3.层级应按金字塔方式调整大小,即金字塔较高的层级被配置为使用比较低层级更少的内存。 堆->堆外->磁盘
*/
@Test
public void test06() {
try (
PersistentCacheManager persistentCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
// 1. 如果您希望使用磁盘存储(如持久Cache实例),您必须向CacheManagerBuilder.persistence()静态方法提供一个数据应存储在磁盘上的位置。
.with(CacheManagerBuilder.persistence(new File(SystemUtil.get("java.io.tmpdir"), "myData")))
.withCache("threeTieredCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
// 堆 保存*个条目
.heap(10, EntryUnit.ENTRIES)
// 堆外
.offheap(1, MemoryUnit.MB)
// 磁盘定义一个持久资源池。它是持久的,因为它应该是(最后一个参数是true)。
.disk(20, MemoryUnit.MB, true)
)
// 配置生存时间到期
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofDays(1)))
)
.build(true);
) {
Cache<Long, String> threeTieredCache = persistentCacheManager.getCache("threeTieredCache", Long.class, String.class);
// 将缓存持久化到硬盘中:C:\Users\*\AppData\Local\Temp\myData\file\threeTieredCache_99af5c58e82ee31980edbfc01dc4f362f30574b4
threeTieredCache.put(1L, "stillAvailableAfterRestart");
// 存储在缓存中的所有值将在 JVM 重新启动后可用
log.info("key=[{}],value=[{}]", 1L, threeTieredCache.get(1L));
}
}
}