CacheManager

This commit is contained in:
redkale
2023-12-11 10:55:03 +08:00
parent d589eef853
commit 8e51f99c7a
12 changed files with 1148 additions and 43 deletions

View File

@@ -45,8 +45,9 @@
【节点全局唯一】 @since 2.8.0
全局Serivce的缓存设置没配置该节点将自动创建一个。
enabled 是否开启缓存功能。默认: true
source: 远程CacheSource的资源名
-->
<caching enabled="true"/>
<caching enabled="true" source="xxx"/>
<!--
【节点全局唯一】

View File

@@ -17,6 +17,7 @@ module org.redkale {
exports org.redkale.asm;
exports org.redkale.boot;
exports org.redkale.boot.watch;
exports org.redkale.caching;
exports org.redkale.cluster;
exports org.redkale.convert;
exports org.redkale.convert.bson;

View File

@@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
* //TODO 待实现
*
* 标记在Service的缓存接口, 方法有以下限制: <br>
* 1、方法返回类型不能是void
* 1、方法返回类型不能是void/CompletableFuture&#60;Void&#62;
* 2、方法必须是protected/public
* 3、方法不能是final
*

View File

@@ -14,10 +14,15 @@ import java.lang.annotation.Target;
* //TODO 待实现
*
* 标记在Service的锁接口, 方法有以下限制: <br>
* 1、方法返回类型不能是void
* 1、方法返回类型不能是void/CompletableFuture&#60;Void&#62;
* 2、方法必须是protected/public
* 3、方法不能是final
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*
* @since 2.8.0
*/
@Inherited

View File

@@ -14,6 +14,7 @@ import java.util.concurrent.TimeUnit;
* 详情见: https://redkale.org
*
* @author zhangjx
*
* @since 2.8.0
*/
@Target({ElementType.METHOD})

View File

@@ -0,0 +1,35 @@
/*
*
*/
package org.redkale.caching;
import org.redkale.convert.json.JsonConvert;
/**
*
* 缓存配置
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*
* @since 2.8.0
*/
public class CacheConfig {
private boolean enabled = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -1,40 +0,0 @@
/*
*
*/
package org.redkale.caching;
import java.lang.reflect.Type;
import org.redkale.source.CacheMemorySource;
import org.redkale.source.CacheSource;
/**
* //TODO 待实现
*
* @author zhangjx
*/
public class CacheFactory {
protected CacheSource localSource = new CacheMemorySource("caching");
protected CacheSource remoteSource;
protected CacheFactory(CacheSource remoteSource) {
this.remoteSource = remoteSource;
}
public static CacheFactory create(CacheSource remoteSource) {
return new CacheFactory(remoteSource);
}
protected long hdelLocal(String map, String key) {
return localSource.hdel(map, key);
}
protected <T> void hsetLocal(final String map, final String key, final Type type, final T value) {
localSource.hset(map, key, type, value);
}
protected <T> T hgetLocal(final String map, final String key, final Type type) {
return localSource.hget(map, key, type);
}
}

View File

@@ -0,0 +1,359 @@
/*
*
*/
package org.redkale.caching;
import java.lang.reflect.Type;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import org.redkale.annotation.Nonnull;
import org.redkale.annotation.Nullable;
import org.redkale.source.CacheMemorySource;
import org.redkale.source.CacheSource;
import org.redkale.util.TypeToken;
/**
* //TODO 待实现
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
*
* @since 2.8.0
*/
public class CacheManager {
//缓存配置项
protected final CacheConfig config;
//数据类型与CacheValue泛型的对应关系
private final ConcurrentHashMap<Type, Type> cacheValueTypes = new ConcurrentHashMap<>();
//本地缓存Source
protected final CacheSource localSource = new CacheMemorySource("caching");
//远程缓存Source
protected CacheSource remoteSource;
protected CacheManager(@Nonnull CacheConfig config, @Nullable CacheSource remoteSource) {
this.config = Objects.requireNonNull(config);
this.remoteSource = remoteSource;
}
public static CacheManager create(@Nonnull CacheConfig config, @Nullable CacheSource remoteSource) {
return new CacheManager(config, remoteSource);
}
//-------------------------------------- 本地缓存 --------------------------------------
/**
* 本地获取缓存数据, 过期返回null
*
* @param <T> 泛型
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
*
* @return 数据值
*/
public <T> T localGet(final String map, final String key, final Type type) {
return get(localSource, map, key, type);
}
/**
* 本地获取字符串缓存数据, 过期返回null
*
* @param map 缓存hash
* @param key 缓存键
*
* @return 数据值
*/
public final String localGetString(final String map, final String key) {
return get(localSource, map, key, String.class);
}
/**
* 本地缓存数据
*
* @param <T> 泛型
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
public <T> void localSet(final String map, final String key, final Type type, final T value, Duration expire) {
set(localSource, map, key, type, value, expire);
}
/**
* 本地缓存字符串数据
*
* @param map 缓存hash
* @param key 缓存键
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
public void localSetString(final String map, final String key, final String value, Duration expire) {
set(localSource, map, key, String.class, value, expire);
}
/**
* 本地删除缓存数据
*
* @param map 缓存hash
* @param key 缓存键
*
* @return 删除数量
*/
public long localDel(String map, String key) {
return del(localSource, map, key);
}
//-------------------------------------- 远程缓存 --------------------------------------
/**
* 远程获取缓存数据, 过期返回null
*
* @param <T> 泛型
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
*
* @return 数据值
*/
public <T> T remoteGet(final String map, final String key, final Type type) {
return get(remoteSource, map, key, type);
}
/**
* 远程异步获取缓存数据, 过期返回null
*
* @param <T> 泛型
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
*
* @return 数据值
*/
public <T> CompletableFuture<T> remoteGetAsync(final String map, final String key, final Type type) {
return getAsync(remoteSource, map, key, type);
}
/**
* 远程获取字符串缓存数据, 过期返回null
*
* @param map 缓存hash
* @param key 缓存键
*
* @return 数据值
*/
public final String remoteGetString(final String map, final String key) {
return get(remoteSource, map, key, String.class);
}
/**
* 远程异步获取字符串缓存数据, 过期返回null
*
* @param map 缓存hash
* @param key 缓存键
*
* @return 数据值
*/
public final CompletableFuture<String> remoteGetStringAsync(final String map, final String key) {
return getAsync(remoteSource, map, key, String.class);
}
/**
* 远程缓存数据
*
* @param <T> 泛型
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
public <T> void remoteSet(final String map, final String key, final Type type, final T value, Duration expire) {
set(remoteSource, map, key, type, value, expire);
}
/**
* 远程异步缓存数据
*
* @param <T> 泛型
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
public <T> CompletableFuture<Void> remoteSetAsync(final String map, final String key, final Type type, final T value, Duration expire) {
return setAsync(remoteSource, map, key, type, value, expire);
}
/**
* 远程缓存字符串数据
*
* @param map 缓存hash
* @param key 缓存键
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
public void remoteSetString(final String map, final String key, final String value, Duration expire) {
set(remoteSource, map, key, String.class, value, expire);
}
/**
* 远程异步缓存字符串数据
*
* @param map 缓存hash
* @param key 缓存键
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
public CompletableFuture<Void> remoteSetStringAsync(final String map, final String key, final String value, Duration expire) {
return setAsync(remoteSource, map, key, String.class, value, expire);
}
/**
* 远程删除缓存数据
*
* @param map 缓存hash
* @param key 缓存键
*
* @return 删除数量
*/
public long remoteDel(String map, String key) {
return del(remoteSource, map, key);
}
/**
* 远程异步删除缓存数据
*
* @param map 缓存hash
* @param key 缓存键
*
* @return 删除数量
*/
public CompletableFuture<Long> remoteDelAsync(String map, String key) {
return delAsync(remoteSource, map, key);
}
//-------------------------------------- 内部方法 --------------------------------------
/**
* 获取缓存数据, 过期返回null
*
* @param <T> 泛型
* @param source 缓存源
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
*
* @return 数据值
*/
protected <T> T get(final CacheSource source, final String map, final String key, final Type type) {
CacheValue<T> val = source.hget(map, key, loadCacheType(type));
return val != null && !val.isExpired() ? val.getValue() : null;
}
/**
* 获取缓存数据, 过期返回null
*
* @param <T> 泛型
* @param source 缓存源
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
*
* @return 数据值
*/
protected <T> CompletableFuture<T> getAsync(final CacheSource source, final String map, final String key, final Type type) {
return source.hgetAsync(map, key, loadCacheType(type)).thenApply(v -> {
CacheValue<T> val = (CacheValue) v;
return val != null && !val.isExpired() ? (T) val.getValue() : null;
});
}
/**
* 缓存数据
*
* @param <T> 泛型
* @param source 缓存源
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
protected <T> void set(final CacheSource source, final String map, final String key, final Type type, final T value, Duration expire) {
Type t = loadCacheType(type, value);
source.hset(map, key, t, CacheValue.create(value, expire));
}
/**
* 缓存数据
*
* @param <T> 泛型
* @param source 缓存源
* @param map 缓存hash
* @param key 缓存键
* @param type 数据类型
* @param value 数据值
* @param expire 过期时长为null表示永不过期
*/
protected <T> CompletableFuture<Void> setAsync(final CacheSource source, final String map, final String key, final Type type, final T value, Duration expire) {
Type t = loadCacheType(type, value);
return source.hsetAsync(map, key, t, CacheValue.create(value, expire));
}
/**
* 删除缓存数据
*
* @param source 缓存源
* @param map 缓存hash
* @param key 缓存键
*
* @return 删除数量
*/
protected long del(final CacheSource source, String map, String key) {
return source.hdel(map, key);
}
/**
* 删除缓存数据
*
* @param source 缓存源
* @param map 缓存hash
* @param key 缓存键
*
* @return 删除数量
*/
protected CompletableFuture<Long> delAsync(final CacheSource source, String map, String key) {
return source.hdelAsync(map, key);
}
/**
* 创建数据类型创建对应CacheValue泛型
*
* @param type 数据类型为null则取value的类型
* @param value 数据值
*
* @return CacheValue泛型
*/
protected Type loadCacheType(Type type, final Object value) {
return loadCacheType(type == null ? value.getClass() : type);
}
/**
* 创建数据类型创建对应CacheValue泛型
*
* @param type 数据类型
*
* @return CacheValue泛型
*/
protected Type loadCacheType(Type type) {
return cacheValueTypes.computeIfAbsent(type, t -> TypeToken.createParameterizedType(null, CacheValue.class, type));
}
}

View File

@@ -0,0 +1,68 @@
/*
*
*/
package org.redkale.caching;
import java.time.Duration;
import org.redkale.convert.ConvertColumn;
import org.redkale.convert.ConvertDisabled;
import org.redkale.convert.json.JsonConvert;
/**
*
* 缓存对象
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 泛型
*
* @since 2.8.0
*/
public class CacheValue<T> {
@ConvertColumn(index = 1)
private T value;
//为0表示不过期
@ConvertColumn(index = 2)
private long time;
public CacheValue() {
}
protected CacheValue(T value, Duration expire) {
this.value = value;
this.time = expire == null ? 0 : (System.currentTimeMillis() + expire.toMillis());
}
public static <T> CacheValue<T> create(T value, Duration expire) {
return new CacheValue(value, expire);
}
@ConvertDisabled
public boolean isExpired() {
return time > 0 && System.currentTimeMillis() > time;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String toString() {
return JsonConvert.root().convertTo(this);
}
}

View File

@@ -47,6 +47,7 @@ public class RedkaleClassLoader extends URLClassLoader {
"org.redkale.asm",
"org.redkale.boot",
"org.redkale.boot.watch",
"org.redkale.caching",
"org.redkale.cluster",
"org.redkale.convert",
"org.redkale.convert.bson",