新增本地缓存基础设施
This commit is contained in:
9
ruoyi-common/src/main/java/com/ruoyi/common/core/cache/InMemoryCacheEntry.java
vendored
Normal file
9
ruoyi-common/src/main/java/com/ruoyi/common/core/cache/InMemoryCacheEntry.java
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
package com.ruoyi.common.core.cache;
|
||||
|
||||
record InMemoryCacheEntry(Object value, Long expireAtMillis)
|
||||
{
|
||||
boolean isExpired(long now)
|
||||
{
|
||||
return expireAtMillis != null && expireAtMillis <= now;
|
||||
}
|
||||
}
|
||||
12
ruoyi-common/src/main/java/com/ruoyi/common/core/cache/InMemoryCacheStats.java
vendored
Normal file
12
ruoyi-common/src/main/java/com/ruoyi/common/core/cache/InMemoryCacheStats.java
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.ruoyi.common.core.cache;
|
||||
|
||||
public record InMemoryCacheStats(
|
||||
String cacheType,
|
||||
String mode,
|
||||
long keySize,
|
||||
long hitCount,
|
||||
long missCount,
|
||||
long expiredCount,
|
||||
long writeCount)
|
||||
{
|
||||
}
|
||||
125
ruoyi-common/src/main/java/com/ruoyi/common/core/cache/InMemoryCacheStore.java
vendored
Normal file
125
ruoyi-common/src/main/java/com/ruoyi/common/core/cache/InMemoryCacheStore.java
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
package com.ruoyi.common.core.cache;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class InMemoryCacheStore
|
||||
{
|
||||
private final ConcurrentHashMap<String, InMemoryCacheEntry> entries = new ConcurrentHashMap<>();
|
||||
private final AtomicLong hitCount = new AtomicLong();
|
||||
private final AtomicLong missCount = new AtomicLong();
|
||||
private final AtomicLong expiredCount = new AtomicLong();
|
||||
private final AtomicLong writeCount = new AtomicLong();
|
||||
|
||||
public void set(String key, Object value)
|
||||
{
|
||||
putEntry(key, new InMemoryCacheEntry(value, null));
|
||||
}
|
||||
|
||||
public void set(String key, Object value, long timeout, TimeUnit unit)
|
||||
{
|
||||
long expireAtMillis = System.currentTimeMillis() + unit.toMillis(timeout);
|
||||
putEntry(key, new InMemoryCacheEntry(value, expireAtMillis));
|
||||
}
|
||||
|
||||
public <T> T get(String key)
|
||||
{
|
||||
InMemoryCacheEntry entry = readEntry(key);
|
||||
return entry == null ? null : (T) entry.value();
|
||||
}
|
||||
|
||||
public boolean hasKey(String key)
|
||||
{
|
||||
return readEntry(key) != null;
|
||||
}
|
||||
|
||||
public boolean delete(String key)
|
||||
{
|
||||
return entries.remove(key) != null;
|
||||
}
|
||||
|
||||
public Set<String> keys(String pattern)
|
||||
{
|
||||
purgeExpiredEntries();
|
||||
Set<String> matchedKeys = new TreeSet<>();
|
||||
entries.forEach((key, value) -> {
|
||||
if (matches(pattern, key))
|
||||
{
|
||||
matchedKeys.add(key);
|
||||
}
|
||||
});
|
||||
return matchedKeys;
|
||||
}
|
||||
|
||||
public InMemoryCacheStats snapshot()
|
||||
{
|
||||
purgeExpiredEntries();
|
||||
return new InMemoryCacheStats(
|
||||
"IN_MEMORY",
|
||||
"single-instance",
|
||||
entries.size(),
|
||||
hitCount.get(),
|
||||
missCount.get(),
|
||||
expiredCount.get(),
|
||||
writeCount.get());
|
||||
}
|
||||
|
||||
private void putEntry(String key, InMemoryCacheEntry entry)
|
||||
{
|
||||
entries.put(key, entry);
|
||||
writeCount.incrementAndGet();
|
||||
}
|
||||
|
||||
private InMemoryCacheEntry readEntry(String key)
|
||||
{
|
||||
InMemoryCacheEntry entry = entries.get(key);
|
||||
if (entry == null)
|
||||
{
|
||||
missCount.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
if (entry.isExpired(System.currentTimeMillis()))
|
||||
{
|
||||
removeExpiredEntry(key, entry);
|
||||
missCount.incrementAndGet();
|
||||
return null;
|
||||
}
|
||||
hitCount.incrementAndGet();
|
||||
return entry;
|
||||
}
|
||||
|
||||
private void purgeExpiredEntries()
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
entries.forEach((key, entry) -> {
|
||||
if (entry.isExpired(now))
|
||||
{
|
||||
removeExpiredEntry(key, entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeExpiredEntry(String key, InMemoryCacheEntry expectedEntry)
|
||||
{
|
||||
if (entries.remove(key, expectedEntry))
|
||||
{
|
||||
expiredCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matches(String pattern, String key)
|
||||
{
|
||||
if ("*".equals(pattern))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (pattern.endsWith("*"))
|
||||
{
|
||||
return key.startsWith(pattern.substring(0, pattern.length() - 1));
|
||||
}
|
||||
return key.equals(pattern);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user