我需要一个简单的缓存来将元组存储在内存中,并具有一定的生存时间。我无法在EHcache网站上找到一种方法,主要包含复杂的使用场景。任何人都可以帮助我吗?
P.S。我没有使用Spring。
答案 0 :(得分:6)
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
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);
在Ehcache 3中,构建器是不可变的,可以安全地共享以从类似的配置创建多个缓存。 如果您使用静态导入,代码将更紧凑,我在这里没有这样做,以便在IDE中轻松粘贴此代码段。
<cache alias="myCache">
<expiry>
<ttl unit="seconds">20</ttl>
</expiry>
<heap>100</heap>
</cache>
Expiry
在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);
}
生存时间匹配getExpiryForCreation
调用,该调用将接收映射的键和值,允许根据映射本身实现不同的过期。
答案 1 :(得分:0)
对于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);
答案 2 :(得分:0)
该解决方案经过测试,可以在Ehcache 3.8.1上正常工作,但是该代码对于任何Ehcache 3.x都肯定有效
首先创建一个类来保留泛型,实际上是您可以传递给缓存的任何对象:
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;
}
}
然后创建一个自定义Expiry类,以实现 Ehcache 3.x 接口 ExpiryPolicy :
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();
}
}
然后您具有正常的代码,但是途中有几行重要提示:
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;
}
}
}