From 58bd2b08a45ee3f95291e80cd76faf845a38a8d0 Mon Sep 17 00:00:00 2001 From: redkale Date: Tue, 26 Dec 2023 14:45:43 +0800 Subject: [PATCH] CacheManager --- docs/cached.md | 49 ++- docs/quick-start.md | 2 +- .../java/org/redkale/cache/CacheManager.java | 411 ++++++++++++++++++ .../java/org/redkale/util/Environment.java | 12 + .../org/redkale/test/cache/CacheInstance.java | 19 +- 5 files changed, 490 insertions(+), 3 deletions(-) diff --git a/docs/cached.md b/docs/cached.md index f1c8470a4..7b98fe49e 100644 --- a/docs/cached.md +++ b/docs/cached.md @@ -1 +1,48 @@ -文档完善中…… \ No newline at end of file +# 方法缓存 +  @Cached注解在Service的方法上,实现对方法结果进行缓存。 +     1、返回类型不能是```void```/```CompletableFuture```
+     2、返回类型必须是可json序列化的
+     3、修饰必须是```protected```/```public```
+     4、修饰不能是```final```/```static```
+ +  将结果进行本地缓存30秒 +```java + @Cached(key = "name", localExpire = "30") + public String getName() { + return "haha"; + } +``` + +  以参数code为key将结果进行本地缓存(时长由环境变量```env.cache.expire```配置,没有配置采用默认值30秒)、远程缓存60秒 +```java + @Cached(key = "#{code}", localExpire = "${env.cache.expire:30}", remoteExpire = "60") + public CompletableFuture getNameAsync(String code) { + return CompletableFuture.completedFuture(code); + } +``` + +  以参数code+map.id为key将结果进行远程缓存60毫秒 +```java + @Resource + private CacheManager cacheManager; + + //实时修改远程缓存的key值 + public void updateName(String code, Map map) { + cacheManager.remoteSetString(code, code + "_" + map.get("id"), Duration.ofMillis(60)); + } + + @Cached(key = "#{code}_#{map.id}", remoteExpire = "60", timeUnit = TimeUnit.MILLISECONDS) + public String getName(String code, Map map) { + return code + "-" + map; + } +``` + +# 缓存配置 +```xml + + +``` \ No newline at end of file diff --git a/docs/quick-start.md b/docs/quick-start.md index a94d8404e..cd940dd1d 100644 --- a/docs/quick-start.md +++ b/docs/quick-start.md @@ -41,7 +41,7 @@ package org.redkalex.example; import org.redkale.net.http.*; import org.redkale.service.Service; -@RestService(automapping = true) +@RestService(autoMapping = true) public class HelloService implements Service { public String sayHello() { diff --git a/src/main/java/org/redkale/cache/CacheManager.java b/src/main/java/org/redkale/cache/CacheManager.java index e4e4e9507..a62a93b59 100644 --- a/src/main/java/org/redkale/cache/CacheManager.java +++ b/src/main/java/org/redkale/cache/CacheManager.java @@ -38,6 +38,19 @@ public interface CacheManager { */ public T localGet(final String hash, final String key, final Type type); + /** + * 本地获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * + * @return 数据值 + */ + default T localGet(final String key, final Type type) { + return localGet(DEFAULT_HASH, key, type); + } + /** * 本地获取字符串缓存数据, 过期返回null * @@ -50,6 +63,18 @@ public interface CacheManager { return localGet(hash, key, String.class); } + /** + * 本地获取字符串缓存数据, 过期返回null + * + * @param hash 缓存hash + * @param key 缓存键 + * + * @return 数据值 + */ + default String localGetString(final String key) { + return localGetString(DEFAULT_HASH, key); + } + /** * 本地获取缓存数据, 过期返回null * @@ -65,6 +90,23 @@ public interface CacheManager { */ public T localGetSet(final String hash, final String key, final Type type, boolean nullable, Duration expire, ThrowSupplier supplier); + /** + * 本地获取缓存数据, 过期返回null + * + * @param 泛型 + * @param hash 缓存hash + * @param key 缓存键 + * @param type 数据类型 + * @param nullable 是否缓存null值 + * @param expire 过期时长,Duration.ZERO为永不过期 + * @param supplier 数据函数 + * + * @return 数据值 + */ + default T localGetSet(final String key, final Type type, boolean nullable, Duration expire, ThrowSupplier supplier) { + return localGetSet(DEFAULT_HASH, key, type, nullable, expire, supplier); + } + /** * 本地异步获取缓存数据, 过期返回null * @@ -80,6 +122,22 @@ public interface CacheManager { */ public CompletableFuture localGetSetAsync(String hash, String key, Type type, boolean nullable, Duration expire, ThrowSupplier> supplier); + /** + * 本地异步获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param nullable 是否缓存null值 + * @param expire 过期时长,Duration.ZERO为永不过期 + * @param supplier 数据函数 + * + * @return 数据值 + */ + default CompletableFuture localGetSetAsync(String key, Type type, boolean nullable, Duration expire, ThrowSupplier> supplier) { + return localGetSetAsync(DEFAULT_HASH, key, type, nullable, expire, supplier); + } + /** * 本地缓存数据 * @@ -92,6 +150,19 @@ public interface CacheManager { */ public void localSet(String hash, String key, Type type, T value, Duration expire); + /** + * 本地缓存数据 + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param value 数据值 + * @param expire 过期时长,Duration.ZERO为永不过期 + */ + default void localSet(String key, Type type, T value, Duration expire) { + localSet(DEFAULT_HASH, key, type, value, expire); + } + /** * 本地缓存字符串数据 * @@ -104,6 +175,17 @@ public interface CacheManager { localSet(hash, key, String.class, value, expire); } + /** + * 本地缓存字符串数据 + * + * @param key 缓存键 + * @param value 数据值 + * @param expire 过期时长,Duration.ZERO为永不过期 + */ + default void localSetString(final String key, final String value, Duration expire) { + localSetString(DEFAULT_HASH, key, value, expire); + } + /** * 本地删除缓存数据 * @@ -114,6 +196,17 @@ public interface CacheManager { */ public long localDel(String hash, String key); + /** + * 本地删除缓存数据 + * + * @param key 缓存键 + * + * @return 删除数量 + */ + default long localDel(String key) { + return localDel(DEFAULT_HASH, key); + } + //-------------------------------------- 远程缓存 -------------------------------------- /** * 远程获取缓存数据, 过期返回null @@ -127,6 +220,19 @@ public interface CacheManager { */ public T remoteGet(final String hash, final String key, final Type type); + /** + * 远程获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * + * @return 数据值 + */ + default T remoteGet(final String key, final Type type) { + return remoteGet(DEFAULT_HASH, key, type); + } + /** * 远程获取字符串缓存数据, 过期返回null * @@ -139,6 +245,17 @@ public interface CacheManager { return remoteGet(hash, key, String.class); } + /** + * 远程获取字符串缓存数据, 过期返回null + * + * @param key 缓存键 + * + * @return 数据值 + */ + default String remoteGetString(final String key) { + return remoteGetString(DEFAULT_HASH, key); + } + /** * 远程异步获取缓存数据, 过期返回null * @@ -151,6 +268,19 @@ public interface CacheManager { */ public CompletableFuture remoteGetAsync(final String hash, final String key, final Type type); + /** + * 远程异步获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * + * @return 数据值 + */ + default CompletableFuture remoteGetAsync(final String key, final Type type) { + return remoteGetAsync(DEFAULT_HASH, key, type); + } + /** * 远程异步获取字符串缓存数据, 过期返回null * @@ -163,6 +293,17 @@ public interface CacheManager { return remoteGetAsync(hash, key, String.class); } + /** + * 远程异步获取字符串缓存数据, 过期返回null + * + * @param key 缓存键 + * + * @return 数据值 + */ + default CompletableFuture remoteGetStringAsync(final String key) { + return remoteGetStringAsync(DEFAULT_HASH, key); + } + /** * 远程获取缓存数据, 过期返回null * @@ -179,6 +320,23 @@ public interface CacheManager { public T remoteGetSet(final String hash, final String key, final Type type, boolean nullable, Duration expire, ThrowSupplier supplier); + /** + * 远程获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param nullable 是否缓存null值 + * @param expire 过期时长,Duration.ZERO为永不过期 + * @param supplier 数据函数 + * + * @return 数据值 + */ + default T remoteGetSet(final String key, final Type type, boolean nullable, + Duration expire, ThrowSupplier supplier) { + return remoteGetSet(DEFAULT_HASH, key, type, nullable, expire, supplier); + } + /** * 远程异步获取缓存数据, 过期返回null * @@ -195,6 +353,23 @@ public interface CacheManager { public CompletableFuture remoteGetSetAsync(String hash, String key, Type type, boolean nullable, Duration expire, ThrowSupplier> supplier); + /** + * 远程异步获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param nullable 是否缓存null值 + * @param expire 过期时长,Duration.ZERO为永不过期 + * @param supplier 数据函数 + * + * @return 数据值 + */ + default CompletableFuture remoteGetSetAsync(String key, Type type, boolean nullable, + Duration expire, ThrowSupplier> supplier) { + return remoteGetSetAsync(DEFAULT_HASH, key, type, nullable, expire, supplier); + } + /** * 远程缓存数据 * @@ -207,6 +382,19 @@ public interface CacheManager { */ public void remoteSet(final String hash, final String key, final Type type, final T value, Duration expire); + /** + * 远程缓存数据 + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param value 数据值 + * @param expire 过期时长,Duration.ZERO为永不过期 + */ + default void remoteSet(final String key, final Type type, final T value, Duration expire) { + remoteSet(DEFAULT_HASH, key, type, value, expire); + } + /** * 远程缓存字符串数据 * @@ -219,6 +407,17 @@ public interface CacheManager { remoteSet(hash, key, String.class, value, expire); } + /** + * 远程缓存字符串数据 + * + * @param key 缓存键 + * @param value 数据值 + * @param expire 过期时长,Duration.ZERO为永不过期 + */ + default void remoteSetString(final String key, final String value, Duration expire) { + remoteSetString(DEFAULT_HASH, key, value, expire); + } + /** * 远程异步缓存数据 * @@ -233,6 +432,21 @@ public interface CacheManager { */ public CompletableFuture remoteSetAsync(String hash, String key, Type type, T value, Duration expire); + /** + * 远程异步缓存数据 + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param value 数据值 + * @param expire 过期时长,Duration.ZERO为永不过期 + * + * @return void + */ + default CompletableFuture remoteSetAsync(String key, Type type, T value, Duration expire) { + return remoteSetAsync(DEFAULT_HASH, type, value, expire); + } + /** * 远程异步缓存字符串数据 * @@ -247,6 +461,19 @@ public interface CacheManager { return remoteSetAsync(hash, key, String.class, value, expire); } + /** + * 远程异步缓存字符串数据 + * + * @param key 缓存键 + * @param value 数据值 + * @param expire 过期时长,Duration.ZERO为永不过期 + * + * @return void + */ + default CompletableFuture remoteSetStringAsync(final String key, final String value, Duration expire) { + return remoteSetStringAsync(DEFAULT_HASH, key, value, expire); + } + /** * 远程删除缓存数据 * @@ -257,6 +484,17 @@ public interface CacheManager { */ public long remoteDel(String hash, String key); + /** + * 远程删除缓存数据 + * + * @param key 缓存键 + * + * @return 删除数量 + */ + default long remoteDel(String key) { + return remoteDel(DEFAULT_HASH, key); + } + /** * 远程异步删除缓存数据 * @@ -267,6 +505,17 @@ public interface CacheManager { */ public CompletableFuture remoteDelAsync(String hash, String key); + /** + * 远程异步删除缓存数据 + * + * @param key 缓存键 + * + * @return 删除数量 + */ + default CompletableFuture remoteDelAsync(String key) { + return remoteDelAsync(DEFAULT_HASH, key); + } + //-------------------------------------- both缓存 -------------------------------------- /** * 本地或远程获取缓存数据, 过期返回null @@ -280,6 +529,19 @@ public interface CacheManager { */ public T bothGet(final String hash, final String key, final Type type); + /** + * 本地或远程获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * + * @return 数据值 + */ + default T bothGet(final String key, final Type type) { + return bothGet(DEFAULT_HASH, key, type); + } + /** * 本地或远程获取字符串缓存数据, 过期返回null * @@ -292,6 +554,17 @@ public interface CacheManager { return bothGet(hash, key, String.class); } + /** + * 本地或远程获取字符串缓存数据, 过期返回null + * + * @param key 缓存键 + * + * @return 数据值 + */ + default String bothGetString(final String key) { + return bothGetString(DEFAULT_HASH, key); + } + /** * 本地或远程异步获取缓存数据, 过期返回null * @@ -304,6 +577,19 @@ public interface CacheManager { */ public CompletableFuture bothGetAsync(final String hash, final String key, final Type type); + /** + * 本地或远程异步获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * + * @return 数据值 + */ + default CompletableFuture bothGetAsync(final String key, final Type type) { + return bothGetAsync(DEFAULT_HASH, key, type); + } + /** * 本地或远程异步获取字符串缓存数据, 过期返回null * @@ -316,6 +602,17 @@ public interface CacheManager { return bothGetAsync(hash, key, String.class); } + /** + * 本地或远程异步获取字符串缓存数据, 过期返回null + * + * @param key 缓存键 + * + * @return 数据值 + */ + default CompletableFuture bothGetStringAsync(final String key) { + return bothGetStringAsync(DEFAULT_HASH, key); + } + /** * 本地或远程获取缓存数据, 过期返回null * @@ -333,6 +630,24 @@ public interface CacheManager { public T bothGetSet(String hash, String key, Type type, boolean nullable, Duration localExpire, Duration remoteExpire, ThrowSupplier supplier); + /** + * 本地或远程获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param nullable 是否缓存null值 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + * @param supplier 数据函数 + * + * @return 数据值 + */ + default T bothGetSet(String key, Type type, boolean nullable, + Duration localExpire, Duration remoteExpire, ThrowSupplier supplier) { + return bothGetSet(DEFAULT_HASH, key, type, nullable, localExpire, remoteExpire, supplier); + } + /** * 本地或远程异步获取缓存数据, 过期返回null * @@ -350,6 +665,24 @@ public interface CacheManager { public CompletableFuture bothGetSetAsync(String hash, String key, Type type, boolean nullable, Duration localExpire, Duration remoteExpire, ThrowSupplier> supplier); + /** + * 本地或远程异步获取缓存数据, 过期返回null + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param nullable 是否缓存null值 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + * @param supplier 数据函数 + * + * @return 数据值 + */ + default CompletableFuture bothGetSetAsync(String key, Type type, boolean nullable, + Duration localExpire, Duration remoteExpire, ThrowSupplier> supplier) { + return bothGetSetAsync(DEFAULT_HASH, key, type, nullable, localExpire, remoteExpire, supplier); + } + /** * 本地和远程缓存数据 * @@ -363,6 +696,20 @@ public interface CacheManager { */ public void bothSet(final String hash, final String key, final Type type, final T value, Duration localExpire, Duration remoteExpire); + /** + * 本地和远程缓存数据 + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param value 数据值 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + */ + default void bothSet(final String key, final Type type, final T value, Duration localExpire, Duration remoteExpire) { + bothSet(DEFAULT_HASH, key, type, value, localExpire, remoteExpire); + } + /** * 本地和远程缓存字符串数据 * @@ -376,6 +723,18 @@ public interface CacheManager { bothSet(hash, key, String.class, value, localExpire, remoteExpire); } + /** + * 本地和远程缓存字符串数据 + * + * @param key 缓存键 + * @param value 数据值 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + */ + default void bothSetString(final String key, final String value, Duration localExpire, Duration remoteExpire) { + bothSet(DEFAULT_HASH, key, String.class, value, localExpire, remoteExpire); + } + /** * 本地和远程异步缓存数据 * @@ -391,6 +750,22 @@ public interface CacheManager { */ public CompletableFuture bothSetAsync(String hash, String key, Type type, T value, Duration localExpire, Duration remoteExpire); + /** + * 本地和远程异步缓存数据 + * + * @param 泛型 + * @param key 缓存键 + * @param type 数据类型 + * @param value 数据值 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + * + * @return void + */ + default CompletableFuture bothSetAsync(String key, Type type, T value, Duration localExpire, Duration remoteExpire) { + return bothSetAsync(DEFAULT_HASH, key, type, value, localExpire, remoteExpire); + } + /** * 本地和远程异步缓存字符串数据 * @@ -406,6 +781,20 @@ public interface CacheManager { return bothSetAsync(hash, key, String.class, value, localExpire, remoteExpire); } + /** + * 本地和远程异步缓存字符串数据 + * + * @param key 缓存键 + * @param value 数据值 + * @param localExpire 本地过期时长,Duration.ZERO为永不过期,为null表示不本地缓存 + * @param remoteExpire 远程过期时长,Duration.ZERO为永不过期,为null表示不远程缓存 + * + * @return void + */ + default CompletableFuture bothSetStringAsync(String key, String value, Duration localExpire, Duration remoteExpire) { + return bothSetAsync(DEFAULT_HASH, key, String.class, value, localExpire, remoteExpire); + } + /** * 本地和远程删除缓存数据 * @@ -416,6 +805,17 @@ public interface CacheManager { */ public long bothDel(String hash, String key); + /** + * 本地和远程删除缓存数据 + * + * @param key 缓存键 + * + * @return 删除数量 + */ + default long bothDel(String key) { + return bothDel(DEFAULT_HASH, key); + } + /** * 本地和远程异步删除缓存数据 * @@ -426,4 +826,15 @@ public interface CacheManager { */ public CompletableFuture bothDelAsync(String hash, String key); + /** + * 本地和远程异步删除缓存数据 + * + * @param key 缓存键 + * + * @return 删除数量 + */ + default CompletableFuture bothDelAsync(String key) { + return bothDelAsync(DEFAULT_HASH, key); + } + } diff --git a/src/main/java/org/redkale/util/Environment.java b/src/main/java/org/redkale/util/Environment.java index 6be2f3a56..f3b04b065 100644 --- a/src/main/java/org/redkale/util/Environment.java +++ b/src/main/java/org/redkale/util/Environment.java @@ -65,6 +65,15 @@ public class Environment implements java.io.Serializable { int pos1 = val.lastIndexOf("${", pos2); if (pos1 >= 0 && pos2 > 0) { String key = val.substring(pos1 + 2, pos2); + int pos3 = key.lastIndexOf(':'); + String defVal = null; + if (pos3 > 0) { + key = key.substring(0, pos3); + defVal = key.substring(pos3 + 1); + if ("null".equals(defVal)) { + defVal = null; + } + } String subVal = properties.getProperty(key); if (subVal != null) { String newVal = getPropertyValue(subVal, envs); @@ -77,6 +86,9 @@ public class Environment implements java.io.Serializable { return getPropertyValue(val.substring(0, pos1) + newVal + val.substring(pos2 + 1)); } } + if (pos3 > 0) { + return defVal; + } throw new RedkaleException("Not found '" + key + "' value"); } } else if ((pos1 >= 0 && pos2 < 0) || (pos1 < 0 && pos2 >= 0 && val.indexOf("#{") < 0)) { diff --git a/src/test/java/org/redkale/test/cache/CacheInstance.java b/src/test/java/org/redkale/test/cache/CacheInstance.java index a8f2f3665..c118acb12 100644 --- a/src/test/java/org/redkale/test/cache/CacheInstance.java +++ b/src/test/java/org/redkale/test/cache/CacheInstance.java @@ -5,9 +5,13 @@ package org.redkale.test.cache; import java.io.File; import java.io.IOException; +import java.time.Duration; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import org.redkale.annotation.Resource; +import org.redkale.cache.CacheManager; import org.redkale.cache.Cached; import org.redkale.service.Service; import org.redkale.source.Range; @@ -19,6 +23,19 @@ import org.redkale.util.RedkaleException; */ public class CacheInstance implements Service { + @Resource + private CacheManager cacheManager; + + //修改远程缓存的key值 + public void updateName(String code, Map map) { + cacheManager.remoteSetString(code, code + "_" + map.get("id"), Duration.ofMillis(60)); + } + + @Cached(key = "#{code}_#{map.id}", remoteExpire = "60", timeUnit = TimeUnit.MILLISECONDS) + public String getName(String code, Map map) { + return code + "-" + map; + } + @Cached(key = "name", localExpire = "30") public String getName() { return "haha"; @@ -49,7 +66,7 @@ public class CacheInstance implements Service { return CompletableFuture.completedFuture(new File("aa.txt")); } - @Cached(key = "info_#{id}_file#{files.one}", localExpire = "30", remoteExpire = "60") + @Cached(key = "info_#{id}_file#{files.one}", localExpire = "30", remoteExpire = "60", timeUnit = TimeUnit.MILLISECONDS) public CompletableFuture> getInfo2Async(ParamBean bean, int id, List idList, Map files) throws IOException, InstantiationException { return CompletableFuture.completedFuture(null); }