This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new 0f931ba [SCB-2060]fix nocas configuration not properly handle yaml
and properties (#1911)
0f931ba is described below
commit 0f931badaa17d393d957170a040c7b1338d8b91f
Author: bao liu <[email protected]>
AuthorDate: Fri Aug 7 16:40:34 2020 +0800
[SCB-2060]fix nocas configuration not properly handle yaml and properties
(#1911)
---
demo/demo-jaxrs/jaxrs-client/pom.xml | 7 ++
.../demo/jaxrs/client/TestDynamicConfig.java | 118 +++++++++++++++++++++
.../demo/jaxrs/client/TestInvokerUtils.java | 55 ++++++++++
.../src/main/resources/microservice.yaml | 28 ++++-
.../servicecomb/config/kie/client/KieUtil.java | 36 ++-----
.../servicecomb/config/kie/client/TestKieUtil.java | 2 +-
dynamic-config/config-nacos/README.md | 41 +------
.../sources/NacosConfigurationSourceImpl.java | 4 +-
.../config/nacos/client/NacosClient.java | 89 +++++++---------
.../config/nacos/client/NacosConfig.java | 32 ++++--
.../config/nacos/client/NacosClientTest.java | 2 +-
.../apache/servicecomb/config/parser/Parser.java | 71 +++++++++++++
.../config/parser/PropertiesParser.java | 41 +++++++
.../servicecomb/config/parser/RawParser.java | 30 ++++++
.../servicecomb/config/parser/YamlParser.java | 34 ++++++
.../servicecomb/config/parser/TestParser.java | 60 +++++++++++
16 files changed, 518 insertions(+), 132 deletions(-)
diff --git a/demo/demo-jaxrs/jaxrs-client/pom.xml
b/demo/demo-jaxrs/jaxrs-client/pom.xml
index cc47a59..23a4dfc 100644
--- a/demo/demo-jaxrs/jaxrs-client/pom.xml
+++ b/demo/demo-jaxrs/jaxrs-client/pom.xml
@@ -45,6 +45,13 @@
<groupId>org.apache.servicecomb</groupId>
<artifactId>provider-pojo</artifactId>
</dependency>
+ <!-- can be added in local test -->
+ <!-- This jar will add an environment version={project.version}, and may
cause spring boot application
+ startup fail -->
+ <!-- <dependency>-->
+ <!-- <groupId>org.apache.servicecomb</groupId>-->
+ <!-- <artifactId>config-nacos</artifactId>-->
+ <!-- </dependency>-->
</dependencies>
<properties>
diff --git
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestDynamicConfig.java
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestDynamicConfig.java
new file mode 100644
index 0000000..2f275a2
--- /dev/null
+++
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestDynamicConfig.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.demo.jaxrs.client;
+
+import java.util.Arrays;
+
+import org.apache.servicecomb.config.inject.InjectProperties;
+import org.apache.servicecomb.config.inject.InjectProperty;
+import org.apache.servicecomb.core.BootListener;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestDynamicConfig implements BootListener {
+
+ @InjectProperties(prefix = "jaxrstest.jaxrsclient")
+ public class Configuration {
+ /*
+ * 方法的 prefix 属性值 "override" 会覆盖标注在类定义的 @InjectProperties
+ * 注解的 prefix 属性值。
+ *
+ * keys属性可以为一个字符串数组,下标越小优先级越高。
+ *
+ * 这里会按照如下顺序的属性名称查找配置属性,直到找到已被配置的配置属性,则停止查找:
+ * 1) jaxrstest.jaxrsclient.override.high
+ * 2) jaxrstest.jaxrsclient.override.low
+ *
+ * 测试用例:
+ * jaxrstest.jaxrsclient.override.high: hello high
+ * jaxrstest.jaxrsclient.override.low: hello low
+ * 预期:
+ * hello high
+ */
+ @InjectProperty(prefix = "jaxrstest.jaxrsclient.override", keys = {"high",
"low"})
+ public String strValue;
+
+ /**
+ * keys支持通配符,并在可以在将配置属性注入的时候指定通配符的代入对象。
+ *
+ * 测试用例:
+ * jaxrstest.jaxrsclient.k.value: 3
+ * 预期:
+ * 3
+ */
+ @InjectProperty(keys = "${key}.value")
+ public int intValue;
+
+ /**
+ * 通配符的代入对象可以是一个字符串List,优先级遵循数组元素下标越小优先级越高策略。
+ *
+ * 测试用例:
+ * jaxrstest.jaxrsclient.l1-1: 3.0
+ * jaxrstest.jaxrsclient.l1-2: 2.0
+ *
+ * 预期:
+ * 3.0
+ */
+ @InjectProperty(keys = "${full-list}")
+ public float floatValue;
+
+ /**
+ * keys属性也支持多个通配符,优先级如下:首先通配符的优先级从左到右递减,
+ * 然后如果通配符被代入List,遵循List中元素index越小优先级越高策略。
+ *
+ * 测试用例:
+ * jaxrstest.jaxrsclient.low-1.a.high-1.b: 1
+ * jaxrstest.jaxrsclient.low-1.a.high-2.b: 2
+ * jaxrstest.jaxrsclient.low-2.a.high-1.b: 3
+ * jaxrstest.jaxrsclient.low-2.a.high-2.b: 4
+ * 预期:
+ * 1
+ */
+ @InjectProperty(keys = "${low-list}.a.${high-list}.b")
+ public long longValue;
+
+ /**
+ * 可以通过注解的defaultValue属性指定默认值。如果字段未关联任何配置属性,
+ * 定义的默认值会生效,否则默认值会被覆盖。
+ *
+ * 测试用例:
+ * 预期:
+ * abc
+ */
+ @InjectProperty(defaultValue = "abc")
+ public String strDef;
+ }
+
+ public void onAfterRegistry(BootEvent event) {
+ Configuration configuration =
SCBEngine.getInstance().getPriorityPropertyManager()
+ .createConfigObject(Configuration.class,
+ "key", "k",
+ "low-list", Arrays.asList("low-1", "low-2"),
+ "high-list", Arrays.asList("high-1", "high-2"),
+ "full-list", Arrays.asList("l1-1", "l1-2")
+ );
+ TestMgr.check(configuration.strValue, "hello high");
+ TestMgr.check(configuration.intValue, 3);
+ TestMgr.check(configuration.floatValue, 3.0);
+ TestMgr.check(configuration.longValue, 1);
+ TestMgr.check(configuration.strDef, "abc");
+ }
+}
diff --git
a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestInvokerUtils.java
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestInvokerUtils.java
new file mode 100644
index 0000000..6f1f4d0
--- /dev/null
+++
b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestInvokerUtils.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.demo.jaxrs.client;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.servicecomb.core.provider.consumer.InvokerUtils;
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.demo.server.User;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+
+@Component
+public class TestInvokerUtils implements CategorizedTestCase {
+ private static final String SERVICE_NAME = "jaxrs";
+
+ private static final String SCHEMA_ID = "codeFirst";
+
+ public void testAllTransport() throws Exception {
+ testCodeFirstJaxrs();
+ }
+
+ // invoke CodeFirstJaxrs
+ private void testCodeFirstJaxrs() {
+ Map<String, Object> swaggerArguments = new HashMap<>();
+ Map<String, User> userMap = new HashMap<>();
+ User user = new User();
+ user.setName("hello");
+ userMap.put("user", user);
+ swaggerArguments.put("userMap", userMap);
+ TypeReference<Map<String, User>> type = new TypeReference<Map<String,
User>>() {
+ };
+ Map<String, User> result = InvokerUtils.syncInvoke(SERVICE_NAME,
SCHEMA_ID, "testUserMap", swaggerArguments,
+ type.getType());
+ TestMgr.check(result.get("user").getName(), userMap.get("user").getName());
+ }
+}
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml
b/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml
index 1559f53..c824285 100644
--- a/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml
@@ -42,4 +42,30 @@ servicecomb:
sayHello:
timeout: 30000
add:
- timeout: 1000
\ No newline at end of file
+ timeout: 1000
+
+# test configurations. you can choose any implementation. default using local.
+
+ # using nacos configuration
+# nacos:
+# serverAddr: http://127.0.0.1:8848
+# group: jaxrstest
+# dataId: jaxrsclient
+# namespace: public
+# contentType: properties # can be properties, yaml, raw. If using raw,
property [group].[dataId]=value.
+# addPrefix: false # if true [group].[dataId] will added as properties/yaml
items prefix. Will not influence raw.
+
+ # for integration test not install any config server
+jaxrstest:
+ jaxrsclient:
+ override.high: hello high
+ override.low: hello low
+ k.value: 3
+ l1-1: 3.0
+ l1-2: 2.0
+ low-1.a.high-1.b: 1
+ low-1.a.high-2.b: 2
+ low-2.a.high-1.b: 3
+ low-2.a.high-2.b: 4
+
+# test configurations.
\ No newline at end of file
diff --git
a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java
b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java
index 74b2a4d..6e209bb 100644
---
a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java
+++
b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/client/KieUtil.java
@@ -17,13 +17,11 @@
package org.apache.servicecomb.config.kie.client;
-import java.io.StringReader;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
@@ -34,10 +32,9 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.servicecomb.config.kie.model.KVDoc;
import org.apache.servicecomb.config.kie.model.KVResponse;
import org.apache.servicecomb.config.kie.model.ValueType;
+import org.apache.servicecomb.config.parser.Parser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
-import org.springframework.core.io.ByteArrayResource;
public class KieUtil {
@@ -109,32 +106,15 @@ public class KieUtil {
return resultMap;
}
- public static Map<String, String> processValueType(KVDoc kvDoc) {
+ public static Map<String, Object> processValueType(KVDoc kvDoc) {
ValueType valueType = parseValueType(kvDoc.getValueType());
-
- Properties properties = new Properties();
- Map<String, String> kvMap = new HashMap<>();
- try {
- if (valueType == (ValueType.YAML) || valueType == (ValueType.YML)) {
- YamlPropertiesFactoryBean yamlFactory = new
YamlPropertiesFactoryBean();
- yamlFactory.setResources(new
ByteArrayResource(kvDoc.getValue().getBytes()));
- properties = yamlFactory.getObject();
- } else if (valueType == (ValueType.PROPERTIES)) {
- properties.load(new StringReader(kvDoc.getValue()));
- } else if (valueType == (ValueType.TEXT) || valueType ==
(ValueType.STRING)) {
- kvMap.put(kvDoc.getKey(), kvDoc.getValue());
- return kvMap;
- } else {
- // ValueType.JSON
- kvMap.put(kvDoc.getKey(), kvDoc.getValue());
- return kvMap;
- }
- kvMap = toMap(kvDoc.getKey(), properties);
- return kvMap;
- } catch (Exception e) {
- LOGGER.error("read config failed", e);
+ if (valueType == (ValueType.YAML) || valueType == (ValueType.YML)) {
+ return
Parser.findParser(Parser.CONTENT_TYPE_YAML).parse(kvDoc.getValue(),
kvDoc.getKey(), true);
+ } else if (valueType == (ValueType.PROPERTIES)) {
+ return
Parser.findParser(Parser.CONTENT_TYPE_PROPERTIES).parse(kvDoc.getValue(),
kvDoc.getKey(), true);
+ } else {
+ return
Parser.findParser(Parser.CONTENT_TYPE_RAW).parse(kvDoc.getValue(),
kvDoc.getKey(), true);
}
- return Collections.emptyMap();
}
private static ValueType parseValueType(String valueType) {
diff --git
a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java
b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java
index a27cf31..55e991e 100644
---
a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java
+++
b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/client/TestKieUtil.java
@@ -29,7 +29,7 @@ public class TestKieUtil {
KVDoc kvDoc = new KVDoc();
kvDoc.setKey("hello");
kvDoc.setValue("world");
- Map<String, String> result = KieUtil.processValueType(kvDoc);
+ Map<String, Object> result = KieUtil.processValueType(kvDoc);
Assert.assertEquals("world", result.get("hello"));
kvDoc.setValueType("text");
diff --git a/dynamic-config/config-nacos/README.md
b/dynamic-config/config-nacos/README.md
index 16fa49d..8e817fc 100644
--- a/dynamic-config/config-nacos/README.md
+++ b/dynamic-config/config-nacos/README.md
@@ -1,40 +1,5 @@
-#config-nacos
-How to use:
-1.Download base model from http://start.servicecomb.io and add maven
dependence:
+# Dynamic configurations implementation with
[Nacos](https://github.com/alibaba/nacos)
-<dependency>
- <groupId>org.apache.servicecomb</groupId>
- <artifactId>config-nacos</artifactId>
- <version>${project.version}</version>
-</dependency>
+Read [developers
guide](https://docs.servicecomb.io/java-chassis/zh_CN/config/general-config/)
+for details.
-2.Start nacos console model(git url:https://github.com/alibaba/nacos) ,both
account and password is "nacos",after that add properties(example):
-Data ID: example
-Group: DEFAULT_GROUP
-JSON:
- {
- "nacos":"666"
- }
-
-3.In base model,add info in microservice.yaml:
-nacos:
- config:
- serverAddr: 127.0.0.1:8848
- dataId: example
- group: DEFAULT_GROUP
-
-4.Then add blow code and start base model,you will get properties(If
properties on nacos has changed, you can also get new value):
-@RestSchema(schemaId = "nacos")
-@RequestMapping(path = "/")
-public class NacosImpl {
- /**
- **get properties from nacos
- */
- @GetMapping(path = "/config")
- @Responsebody
- public String config() throws Exception{
- final String config = DynamicPropertyFactory.getInstance()
- .getStringProperty("nacos","").getValue();
- return JSON.toJSONString(config);
- }
-}
\ No newline at end of file
diff --git
a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImpl.java
b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImpl.java
index 27c463c..13c7eb9 100644
---
a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImpl.java
+++
b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImpl.java
@@ -47,8 +47,6 @@ public class NacosConfigurationSourceImpl implements
ConfigCenterConfigurationSo
private List<WatchedUpdateListener> listeners = new CopyOnWriteArrayList<>();
- private static final String SERVER_ADDR = "nacos.config.serverAddr";
-
public NacosConfigurationSourceImpl() {
}
@@ -56,7 +54,7 @@ public class NacosConfigurationSourceImpl implements
ConfigCenterConfigurationSo
@Override
public boolean isValidSource(Configuration localConfiguration) {
- if (localConfiguration.getProperty(SERVER_ADDR) == null) {
+ if (localConfiguration.getProperty(NacosConfig.SERVER_ADDR) == null) {
LOGGER.warn("Nacos configuration source is not configured!");
return false;
}
diff --git
a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosClient.java
b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosClient.java
index dfa7eb6..290f922 100644
---
a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosClient.java
+++
b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosClient.java
@@ -21,37 +21,28 @@ import static
org.apache.servicecomb.config.nacos.client.ConfigurationAction.CRE
import static
org.apache.servicecomb.config.nacos.client.ConfigurationAction.DELETE;
import static
org.apache.servicecomb.config.nacos.client.ConfigurationAction.SET;
-import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
-import java.util.concurrent.*;
-
-import com.alibaba.nacos.api.NacosFactory;
-import com.alibaba.nacos.api.config.ConfigService;
-import com.alibaba.nacos.api.config.listener.Listener;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import org.apache.commons.lang3.StringUtils;
import
org.apache.servicecomb.config.nacos.archaius.sources.NacosConfigurationSourceImpl.UpdateHandler;
-import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.config.parser.Parser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.fasterxml.jackson.core.type.TypeReference;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.config.listener.Listener;
public class NacosClient {
private static final Logger LOGGER =
LoggerFactory.getLogger(NacosClient.class);
- private static final NacosConfig NACOS_CONFIG = NacosConfig.INSTANCE;
-
private static final Map<String, Object> originalConfigMap = new
ConcurrentHashMap<>();
- private final String serverAddr = NACOS_CONFIG.getServerAddr();
-
- private final String dataId = NACOS_CONFIG.getDataId();
-
- private final String group = NACOS_CONFIG.getGroup();
-
private final UpdateHandler updateHandler;
public NacosClient(UpdateHandler updateHandler) {
@@ -59,59 +50,55 @@ public class NacosClient {
}
public void refreshNacosConfig() {
- new ConfigRefresh(serverAddr, dataId, group).refreshConfig();
+ new ConfigRefresh().refreshConfig();
}
class ConfigRefresh {
- private final String serverAddr;
-
- private final String dataId;
+ Parser contentParser =
Parser.findParser(NacosConfig.INSTANCE.getContentType());
- private final String group;
+ String keyPrefix = NacosConfig.INSTANCE.getGroup() + "." +
+ NacosConfig.INSTANCE.getDataId();
- ConfigRefresh(String serverAddr, String dataId, String group) {
- this.serverAddr = serverAddr;
- this.dataId = dataId;
- this.group = group;
+ ConfigRefresh() {
}
@SuppressWarnings("unchecked")
void refreshConfig() {
Properties properties = new Properties();
- properties.put("serverAddr", serverAddr);
- properties.put("dataId", dataId);
- properties.put("group", group);
+ properties.put("serverAddr", NacosConfig.INSTANCE.getServerAddr());
+ properties.put("namespace", NacosConfig.INSTANCE.getNameSpace());
+
try {
ConfigService configService =
NacosFactory.createConfigService(properties);
- String content = configService.getConfig(dataId, group, 5000);
- Map<String, Object> body = JsonUtils.OBJ_MAPPER.readValue(content,
- new TypeReference<Map<String, Object>>() {
+ String content =
configService.getConfig(NacosConfig.INSTANCE.getDataId(),
+ NacosConfig.INSTANCE.getGroup(), 5000);
+ processContent(content);
+ configService.addListener(NacosConfig.INSTANCE.getDataId(),
+ NacosConfig.INSTANCE.getGroup(), new Listener() {
+ @Override
+ public void receiveConfigInfo(String configInfo) {
+ LOGGER.info("receive from nacos:" + configInfo);
+ processContent(configInfo);
+ }
+
+ @Override
+ public Executor getExecutor() {
+ return null;
+ }
});
- refreshConfigItems(body);
- configService.addListener(dataId, group, new Listener() {
- @Override
- public void receiveConfigInfo(String configInfo) {
- LOGGER.info("receive from nacos:" + configInfo);
- try {
- Map<String, Object> body =
JsonUtils.OBJ_MAPPER.readValue(configInfo,
- new TypeReference<Map<String, Object>>() {
- });
- refreshConfigItems(body);
- } catch (IOException e) {
- LOGGER.error("JsonObject parse config center response error: ",
e);
- }
- }
-
- @Override
- public Executor getExecutor() {
- return null;
- }
- });
} catch (Exception e) {
LOGGER.error("Receive nacos config error: ", e);
}
}
+ private void processContent(String content) {
+ if (StringUtils.isEmpty(content)) {
+ return;
+ }
+
+ refreshConfigItems(contentParser.parse(content, keyPrefix,
NacosConfig.INSTANCE.getAddPrefix()));
+ }
+
private void refreshConfigItems(Map<String, Object> map) {
compareChangedConfig(originalConfigMap, map);
originalConfigMap.clear();
diff --git
a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosConfig.java
b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosConfig.java
index dc41ca8..4fb3111 100644
---
a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosConfig.java
+++
b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosConfig.java
@@ -24,11 +24,17 @@ public class NacosConfig {
private static Configuration finalConfig;
- private static final String DATA_ID = "servicecomb.nacos.dataId";
+ public static final String DATA_ID = "servicecomb.nacos.dataId";
- private static final String SERVER_ADDR = "servicecomb.nacos.serverAddr";
+ public static final String SERVER_ADDR = "servicecomb.nacos.serverAddr";
- private static final String GROUP = "servicecomb.nacos.group";
+ public static final String GROUP = "servicecomb.nacos.group";
+
+ public static final String ADD_PREFIX = "servicecomb.nacos.addPrefix";
+
+ public static final String NAME_SPACE = "servicecomb.nacos.namespace";
+
+ public static final String CONTENT_TYPE = "servicecomb.nacos.contentType";
private NacosConfig() {
}
@@ -37,19 +43,27 @@ public class NacosConfig {
finalConfig = config;
}
- public Configuration getConcurrentCompositeConfiguration() {
- return finalConfig;
- }
-
public String getServerAddr() {
return finalConfig.getString(SERVER_ADDR);
}
- public String getDataId(){
+ public String getDataId() {
return finalConfig.getString(DATA_ID);
}
- public String getGroup(){
+ public String getGroup() {
return finalConfig.getString(GROUP);
}
+
+ public String getNameSpace() {
+ return finalConfig.getString(NAME_SPACE, "public");
+ }
+
+ public String getContentType() {
+ return finalConfig.getString(CONTENT_TYPE, "yaml");
+ }
+
+ public boolean getAddPrefix() {
+ return finalConfig.getBoolean(ADD_PREFIX, true);
+ }
}
diff --git
a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosClientTest.java
b/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosClientTest.java
index d48c11b..9484517 100644
---
a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosClientTest.java
+++
b/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosClientTest.java
@@ -61,7 +61,7 @@ public class NacosClientTest {
UpdateHandler updateHandler = impl.new UpdateHandler();
NacosClient nacosClient = new NacosClient(updateHandler);
- NacosClient.ConfigRefresh cr = nacosClient.new ConfigRefresh("","","");
+ NacosClient.ConfigRefresh cr = nacosClient.new ConfigRefresh();
try {
Deencapsulation.invoke(cr, "compareChangedConfig", before, after);
diff --git
a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/Parser.java
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/Parser.java
new file mode 100644
index 0000000..216253a
--- /dev/null
+++
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/Parser.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.parser;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.lang3.StringUtils;
+
+public interface Parser {
+ String CONTENT_TYPE_YAML = "yaml";
+ String CONTENT_TYPE_PROPERTIES = "properties";
+ String CONTENT_TYPE_RAW = "raw";
+
+ YamlParser yamlParser = new YamlParser();
+ PropertiesParser propertiesParser = new PropertiesParser();
+ RawParser rawParser = new RawParser();
+
+ Map<String, Object> parse(String content, String prefix, boolean addPrefix);
+
+ static Parser findParser(String contentType) {
+ switch (contentType) {
+ case CONTENT_TYPE_YAML:
+ return yamlParser;
+ case CONTENT_TYPE_PROPERTIES:
+ return propertiesParser;
+ case CONTENT_TYPE_RAW:
+ return rawParser;
+ default:
+ throw new IllegalArgumentException("not supported contentType=" +
contentType);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ static Map<String, Object> propertiesToMap(Properties properties, String
prefix, boolean addPrefix) {
+ Map<String, Object> result = new HashMap<>();
+ Enumeration<String> keys = (Enumeration<String>)
properties.propertyNames();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ String value = properties.getProperty(key);
+
+ if (addPrefix && !StringUtils.isEmpty(prefix)) {
+ key = prefix + "." + key;
+ }
+
+ if (value == null) {
+ result.put(key, null);
+ } else {
+ result.put(key, value.trim());
+ }
+ }
+ return result;
+ }
+}
diff --git
a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/PropertiesParser.java
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/PropertiesParser.java
new file mode 100644
index 0000000..84bfae1
--- /dev/null
+++
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/PropertiesParser.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.parser;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Map;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PropertiesParser implements Parser {
+ private static final Logger LOGGER =
LoggerFactory.getLogger(PropertiesParser.class);
+
+ @Override
+ public Map<String, Object> parse(String content, String prefix, boolean
addPrefix) {
+ Properties properties = new Properties();
+ try {
+ properties.load(new StringReader(content));
+ } catch (IOException e) {
+ LOGGER.error("parse properties content failed, message={}",
e.getMessage());
+ }
+ return Parser.propertiesToMap(properties, prefix, addPrefix);
+ }
+}
diff --git
a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/RawParser.java
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/RawParser.java
new file mode 100644
index 0000000..b22d52d
--- /dev/null
+++
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/RawParser.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.parser;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class RawParser implements Parser {
+ @Override
+ public Map<String, Object> parse(String content, String prefix, boolean
addPrefix) {
+ Map<String, Object> result = new HashMap<>();
+ result.put(prefix, content);
+ return result;
+ }
+}
diff --git
a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/YamlParser.java
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/YamlParser.java
new file mode 100644
index 0000000..4ce5665
--- /dev/null
+++
b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/YamlParser.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.parser;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
+import org.springframework.core.io.ByteArrayResource;
+
+public class YamlParser implements Parser {
+ @Override
+ public Map<String, Object> parse(String content, String prefix, boolean
addPrefix) {
+ YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
+ yamlFactory.setResources(new ByteArrayResource(content.getBytes()));
+ Properties properties = yamlFactory.getObject();
+ return Parser.propertiesToMap(properties, prefix, addPrefix);
+ }
+}
diff --git
a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/parser/TestParser.java
b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/parser/TestParser.java
new file mode 100644
index 0000000..6940934
--- /dev/null
+++
b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/parser/TestParser.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.parser;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+
+import org.junit.Test;
+
+public class TestParser {
+ @Test
+ public void testRawParser() {
+ Parser parser = Parser.findParser(Parser.CONTENT_TYPE_RAW);
+ assertThat(parser.parse("world", "hello",
true)).containsKey("hello").containsValue("world");
+ assertThat(parser.parse("world", "hello",
false)).containsKey("hello").containsValue("world");
+ }
+
+ @Test
+ public void testPropertiesParser() {
+ Parser parser = Parser.findParser(Parser.CONTENT_TYPE_PROPERTIES);
+ assertThat(parser.parse("l1-1=3.0\n"
+ + "l1-2=2.0", "hello", true)).containsKeys("hello.l1-1", "hello.l1-2")
+ .containsValues("2.0", "3.0");
+ assertThat(parser.parse("l1-1=3.0\n"
+ + "l1-2=2.0", "hello", false)).containsKeys("l1-1", "l1-2")
+ .containsValues("2.0", "3.0");
+ }
+
+ @Test
+ public void testYamlParser() {
+ Parser parser = Parser.findParser(Parser.CONTENT_TYPE_YAML);
+ assertThat(parser.parse("l1-1: 3.0\n"
+ + "l1-2: 2.0", "hello", true)).containsKeys("hello.l1-1", "hello.l1-2")
+ .containsValues("2.0", "3.0");
+ assertThat(parser.parse("l1-1: 3.0\n"
+ + "l1-2: 2.0", "false", false)).containsKeys("l1-1", "l1-2")
+ .containsValues("2.0", "3.0");
+ }
+
+ @Test
+ public void testInvalidParser() {
+ Throwable exception = catchThrowable(() -> Parser.findParser("unknown"));
+ assertThat(exception).isInstanceOf(IllegalArgumentException.class);
+ }
+}