diff --git a/neutrino-core/src/main/java/fun/asgc/neutrino/core/base/Kv.java b/neutrino-core/src/main/java/fun/asgc/neutrino/core/base/Kv.java index 1fdc9df2..ecbdb7f8 100644 --- a/neutrino-core/src/main/java/fun/asgc/neutrino/core/base/Kv.java +++ b/neutrino-core/src/main/java/fun/asgc/neutrino/core/base/Kv.java @@ -18,6 +18,12 @@ import java.util.*; * 1、take开头的方法,适用于配置层。利用parent委托机制,做优先级。 如5级配置:默认值 -> 内部配置文件 -> 环境变量 -> 外部配置文件 -> 启动参数
* 2、inx开头的方法,适用于不关心参数名称,根据下标取值。如普通方法参数、sql顺序参数(非具名参数)
* 3、get方法取值,没有委托机制,适用于sql具名参数、bean方法具名参数
+ * 4、setAlias用于为一个key设置别名,用于解决应用层简化配置,避免冗长的配置名。
+ * + * 注意:
+ * 1、对于key来说,key对于所有上层Kv都是可见的。比如kv1设置了key1,kv2的父级是kv1,那么kv2使用key1能够查找到kv1的配置。
+ * 2、对于alias来说,与key相反。alias对于所有上层kv是不可见的,除非上层kv再次定义了该alias。
+ * 3、所有的key、alias都不区分大小写、忽略-、_符号。
* @author: aoshiguchen * @date: 2023/3/1 */ @@ -51,7 +57,7 @@ public class Kv implements Map , Serializable, Cloneable { } public Kv setAlias(K k, K alias) { - this.aliasMap.put(convertKey(alias), k); + this.aliasMap.put(convertKey(alias), convertKey(k)); return this; } @@ -67,11 +73,7 @@ public class Kv implements Map , Serializable, Cloneable { protected boolean removeEldestEntry(Map.Entry eldest) { boolean doRemove = Kv.this.removeEldestEntry(eldest); if (doRemove) { - if (eldest.getKey() instanceof String) { - _k.remove(convertKey((String) eldest.getKey())); - } else { - _k.remove(eldest.getKey()); - } + _k.remove(convertKey(eldest.getKey())); } return doRemove; } @@ -105,13 +107,7 @@ public class Kv implements Map , Serializable, Cloneable { @Override public boolean containsKey(Object key) { - boolean convertKey = false; - if (key instanceof String) { - convertKey = this._k.containsKey(convertKey((String) key)); - } else { - convertKey = this._k.containsKey(key); - } - return convertKey; + return this._k.containsKey(convertKey(key)); } public boolean stackContainsKey(K k) { @@ -244,21 +240,11 @@ public class Kv implements Map , Serializable, Cloneable { // ====== 为了方便取值操作,get方法保持Map接口原有语义,不支持栈式取值 ======= @Override public V get(Object key) { - K k = this.aliasMap.get(convertKey(key)); - try { - if (null == k) { - k = (K) key; - } - } catch (Exception e) { - return null; + key = convertKey(key); + if (this.aliasMap.containsKey(key)) { + key = this.aliasMap.get(key); } - if (k instanceof String) { - k = this._k.get(convertKey((String) k)); - } - if (null != k) { - return this._m.get(k); - } - return null; + return this._m.get(this._k.get(key)); } public V get(Object key, V defaultValue) { @@ -351,11 +337,19 @@ public class Kv implements Map , Serializable, Cloneable { // ====== 为了方便取值操作,take开头的方法,全部基于栈式取值 ======= public V take(K k) { - return this.stackGet(k); + if (this.aliasMap.containsKey(convertKey(k))) { + return this.stackGet(this.aliasMap.get(convertKey(k))); + } + V res = this.stackGet(k); + return res; } public V take(K k, V defaultValue) { - return this.stackGetOrDefault(k, defaultValue); + V res = take(k); + if (null == res ) { + res = defaultValue; + } + return res; } public String takeStr(K k) { diff --git a/neutrino-core/src/test/java/fun/asgc/neutrino/core/base/KvTest.java b/neutrino-core/src/test/java/fun/asgc/neutrino/core/base/KvTest.java index c3ad5d72..55204ab6 100644 --- a/neutrino-core/src/test/java/fun/asgc/neutrino/core/base/KvTest.java +++ b/neutrino-core/src/test/java/fun/asgc/neutrino/core/base/KvTest.java @@ -10,9 +10,11 @@ import org.junit.Test; public class KvTest { @Test public void test1() { + Object key1 = new Object(); Kv kv1 = Kv.of() .set("app.server.http.http-port", 8080) .set("app.server.http.jks_Path", "/123/456") + .set(key1, 1) .setAlias("app.server.http.http-port", "http-port") ; @@ -22,21 +24,25 @@ public class KvTest { .set("app.server.http.context-path", "/") ; - Kv kv3 = Kv.of(kv2); + Kv kv3 = Kv.of(kv2) + .setAlias("app.server.http.http-port", "port"); Assert.assertTrue(!kv1.isEmpty()); - Assert.assertTrue(kv1.size() == 2); - Assert.assertTrue(kv1.stackSize() == 2); + Assert.assertTrue(kv1.size() == 3); + Assert.assertTrue(kv1.stackSize() == 3); Assert.assertTrue(kv1.get("app.server.http.http-port").equals(8080)); Assert.assertTrue(kv1.get("app.server.http.httpPort").equals(8080)); Assert.assertTrue(kv1.idx(0).equals(8080)); Assert.assertTrue(kv1.get("app.server.http.jks_Path").equals("/123/456")); Assert.assertTrue(kv1.get("app.server.http.jksPath").equals("/123/456")); Assert.assertTrue(kv1.idx(1).equals("/123/456")); + Assert.assertTrue(kv1.containsKey("app.server.http.http-port")); + Assert.assertTrue(kv1.containsKey(key1)); + Assert.assertFalse(kv1.containsKey(new Object())); Assert.assertTrue(!kv2.isEmpty()); Assert.assertTrue(kv2.size() == 2); - Assert.assertTrue(kv2.stackSize() == 4); + Assert.assertTrue(kv2.stackSize() == 5); Assert.assertTrue(kv2.get("app.server.http.http-port").equals(8081)); Assert.assertTrue(kv2.get("app.server.http.httpPort").equals(8081)); Assert.assertTrue(kv2.get("app.server.http.jks-path") == null); @@ -50,7 +56,7 @@ public class KvTest { Assert.assertTrue(kv3.isEmpty()); Assert.assertTrue(!kv3.isStackEmpty()); Assert.assertTrue(kv3.size() == 0); - Assert.assertTrue(kv3.stackSize() == 4); + Assert.assertTrue(kv3.stackSize() == 5); Assert.assertTrue(kv3.get("app.server.http.jks-path") == null); Assert.assertTrue(kv3.get("app.server.http.jksPath") == null); Assert.assertTrue(kv3.get("app.server.http.context-path") == null); @@ -61,8 +67,11 @@ public class KvTest { Assert.assertTrue(kv3.stackGetOrDefault("app.server.http.timeout", 60000).equals(60000)); Assert.assertTrue(kv3.takeStr("app.server.http.http-port").equals("8081")); + Assert.assertNull(kv3.take(null)); + // 注意:http-port是第1层设置的别名,因此用这个别名对2、3层不可见,不会指向第二层的8081(除非第2、3层定义了同样的别名) Assert.assertTrue(kv3.takeStr("httpPort").equals("8080")); Assert.assertTrue(kv3.takeInt("http-port").equals(8080)); - + // 注意:第3层设置的别名port,找到第二层的配置,不再往上找 + Assert.assertTrue(kv3.takeInt("port").equals(8081)); } }