[英]EHcache simple example with time-to-live
I need a simple cache for storing tuples in memory with a certain time-to-live.我需要一个简单的缓存来在内存中存储具有特定生存时间的元组。 I couldn't find a way to do that on EHcache website, which contains mostly complex usage scenarios.
我在 EHcache 网站上找不到这样做的方法,该网站主要包含复杂的使用场景。 Can anyone help me out?
任何人都可以帮助我吗?
PS I don't use Spring. PS我不使用Spring。
CacheManager cacheManager = initCacheManager();
CacheConfiguration cacheConfiguration = new CacheConfiguration().name("myCache")
.maxEntriesLocalHeap(100)
.timeToLiveSeconds(20);
cacheManager.addCache(new Cache(cacheConfiguration));
<cache name="myCache"
maxEntriesLocalHeap="100"
timeToLiveSeconds="20"/>
Element
Element
Ehcache 2.x allows your to override expiry settings per Element
: Ehcache 2.x 允许您覆盖每个
Element
到期设置:
Element element = new Element("key", "value");
element.setTimeToLive(10);
cache.put(element);
CacheManager cacheManager = initCacheManager();
CacheConfigurationBuilder<Long, String> configuration =
CacheConfigurationBuilder.newCacheConfigurationBuilder(Long.class, String.class, ResourcePoolsBuilder
.heap(100))
.withExpiry(Expirations.timeToLiveExpiration(new Duration(20, TimeUnit.SECONDS)));
cacheManager.createCache("myCache", configuration);
In Ehcache 3, the builder is immutable and can be safely shared to create multiple caches from a similar configuration.在 Ehcache 3 中,构建器是不可变的,可以安全地共享以从类似的配置创建多个缓存。 And the code will be more compact if you use static imports, which I did not do here to ease pasting this snippet in an IDE.
如果您使用静态导入,代码会更加紧凑,我在这里没有这样做是为了简化在 IDE 中粘贴此代码段的过程。
<cache alias="myCache">
<expiry>
<ttl unit="seconds">20</ttl>
</expiry>
<heap>100</heap>
</cache>
Expiry
Expiry
覆盖in Ehcache 3.x, Expiry
is an interface which users can implement:在 Ehcache 3.x 中,
Expiry
是一个用户可以实现的接口:
public interface Expiry<K, V> {
Duration getExpiryForCreation(K key, V value);
Duration getExpiryForAccess(K key, ValueSupplier<? extends V> value);
Duration getExpiryForUpdate(K key, ValueSupplier<? extends V> oldValue, V newValue);
}
time-to-live matches the getExpiryForCreation
invocation, which will receive the key and value of the mapping, allowing to implement different expirations depending on the mapping itself.生存时间匹配
getExpiryForCreation
调用,它将接收映射的键和值,允许根据映射本身实现不同的到期时间。
This solution was tested as working fine on Ehcache 3.8.1, but the code is for sure valid for any Ehcache 3.x此解决方案在 Ehcache 3.8.1 上测试正常,但代码肯定对任何 Ehcache 3.x 都有效
First create a class to keep a generic, in fact any object you are able pass to cache:首先创建一个类来保持一个泛型,实际上任何你可以传递给缓存的对象:
import java.io.Serializable;
import java.time.Duration;
public class EhcacheValue<T> implements Serializable {
private static final long serialVersionUID = 1L;
private T object;
private long timeToLive;
public EhcacheValue(T theObject, Duration theDuration) {
object = theObject;
timeToLive = theDuration.getSeconds();
}
public Duration getTimeToLiveDuration() {
return Duration.ofSeconds(timeToLive);
}
public T getObject() {
return object;
}
public void setObject(T theObject) {
object = theObject;
}
public long getTimeToLive() {
return timeToLive;
}
public void setTimeToLive(long theTimeToLive) {
timeToLive = theTimeToLive;
}
}
Then create a custom Expiry class implementing the Ehcache 3.x interface ExpiryPolicy :然后创建一个实现Ehcache 3.x接口ExpiryPolicy的自定义 Expiry 类:
import java.time.Duration;
import java.util.function.Supplier;
import org.ehcache.expiry.ExpiryPolicy;
public class CustomExpiryPolicy<K, V extends EhcacheValue<?>> implements ExpiryPolicy<K, V> {
public CustomExpiryPolicy() {
}
@Override
public Duration getExpiryForCreation(K theKey, V theValue) {
return theValue.getTimeToLiveDuration();
}
@Override
public Duration getExpiryForAccess(K theKey, Supplier<? extends V> theValue) {
return null;
}
@Override
public Duration getExpiryForUpdate(K theKey, Supplier<? extends V> theOldValue, V theNewValue) {
return theNewValue.getTimeToLiveDuration();
}
}
Then you have the normal code, but with a few important lines on the way :然后你有正常的代码,但有一些重要的行:
public class TestEhCache {
private static final String CACHE_TIER_HEAP = "OnHeap";
public static void main(String[] args) {
StatisticsService statisticsService = new DefaultStatisticsService();
myCacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.using(statisticsService)
.build();
//we init it here, not with boolean in build()
myCacheManager.init();
// Beware, the items are not expiring automatically, there are more mechanism in place for checking the expiration
// For instance the expiration is checked at get time
// for more details see the documentation from the version 2.8
// here: https://www.ehcache.org/documentation/2.8/apis/cache-event-listeners.html
// Unfortunately for the version 3.x doesn't exist a detailed depiction, but in main the procedure is the same
//
// Ehcache 2.8 documentation:
// Elements are checked for expiry in Ehcache at the following times:
//
// When a get request is made
// When an element is spooled to the diskStore in accordance with a MemoryStore eviction policy
// In the DiskStore when the expiry thread runs, which by default is
// net.sf.ehcache.Cache#DEFAULT_EXPIRY_THREAD_INTERVAL_SECONDS
CustomExpiryPolicy<String,EhcacheValue<?>> expiryPolicy = new CustomExpiryPolicy<String,EhcacheValue<?>>();
ResourcePools resourcePools = ResourcePoolsBuilder.newResourcePoolsBuilder().heap(2000L, EntryUnit.ENTRIES).build();
@SuppressWarnings("unchecked")
Class<EhcacheValue<?>> myEhcacheValue = (Class<EhcacheValue<?>>)(Class<?>)EhcacheValue.class;
CacheConfiguration<String,EhcacheValue<?>> cacheConfiguration = CacheConfigurationBuilder
.newCacheConfigurationBuilder(String.class, myEhcacheValue, resourcePools)
.withExpiry(expiryPolicy)
//.withService(new StoreStatisticsConfiguration(true)) // explicitly enable statistics, it seems is not needed
.build();
myCache = myCacheManager.createCache("myCache", cacheConfiguration);
myCacheStatistics = statisticsService.getCacheStatistics("myCache");
long cacheEntriesNr = myCacheStatistics.getTierStatistics().get(CACHE_TIER_HEAP).getMappings();
//nb element in heap tier
long sizeEntriesByStatistics = myCacheStatistics.getTierStatistics().get("OnHeap").getMappings();
//size of the tier in memory, when you set memory limits, not in this case
//long sizeBytesByStatistics = myCacheStatistics.getTierStatistics().get("OnHeap").getOccupiedByteSize();
long getsCnt = myCacheStatistics.getCacheGets();
long putsCnt = myCacheStatistics.getCachePuts();
long removalsCnt = myCacheStatistics.getCacheRemovals();
long missesCnt = myCacheStatistics.getCacheMisses();
long evictionsCnt = myCacheStatistics.getCacheEvictions();
long crtExpiredCnt = myCacheStatistics.getCacheExpirations();
System.out.println("getsCnt = "+getsCnt);
System.out.println("putsCnt = "+putsCnt);
System.out.println("removalsCnt = "+removalsCnt);
System.out.println("missesCnt = "+missesCnt);
System.out.println("evictionsCnt = "+evictionsCnt);
System.out.println("expiredCnt = "+expiredCnt);
System.out.println("hitPercentage = "+hitPercentage);
System.out.println("missPercentage = "+missPercentage);
System.out.println("Computed number of items in cache = "+(putsCnt-removalsCnt-expiredCnt-evictionsCnt));
}
@SuppressWarnings("unchecked")
// we are aware about the unchecked cast - it is a desired behavior.
// Cache can store objects of various types, so compile time type safety cannot be achieved easily.
// We'll get runtime ClassCastException if cache is used incorrectly.
public static <T> T get(String key) {
EhcacheValue<T> ehcacheValue = (EhcacheValue<T>)myCache.get(key);
return (T) (ehcacheValue!=null?ehcacheValue.getObject():null);
}
// we are aware about the unchecked cast - it is a desired behavior.
// Cache can store objects of various types, so compile time type safety cannot be achieved easily.
// We'll get runtime ClassCastException if cache is used incorrectly.
public static <T extends Object> T put(String key, T value, int timeToLiveInSeconds) {
if (key == null) {
throw new AssertionError("Key must not be null!");
}
if (value != null) {
EhcacheValue<T> ehcacheValue = new EhcacheValue<T>(value, Duration.of(60, ChronoUnit.SECONDS));
myCache.put(key, ehcacheValue);
return value;
} else {
return null;
}
}
}
As for EhCache version 3.3.1, groupId:org.ehcache,artifactId:ehcache
, the following works!对于 EhCache 3.3.1 版,
groupId:org.ehcache,artifactId:ehcache
,以下有效!
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().withCache("AllCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class,String.class,
ResourcePoolsBuilder.heap(100))
.withExpiry(Expirations.timeToLiveExpiration(new Duration(86400, TimeUnit.SECONDS)))
.build()).build(true);
Cache<String, String> allCache = cacheManager.getCache("AllCache", String.class, String.class);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.