mirror of
https://gitee.com/mirrors/Spring-Cloud-Alibaba.git
synced 2021-06-26 13:25:11 +08:00
Merge pull request #1179 from yuhuangbin/nacos-loaddata-orderly
[optimize] Nacos config load data orderly
This commit is contained in:
commit
dbba024538
@ -17,9 +17,8 @@
|
|||||||
package com.alibaba.cloud.nacos.client;
|
package com.alibaba.cloud.nacos.client;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import com.alibaba.cloud.nacos.NacosPropertySourceRepository;
|
import com.alibaba.cloud.nacos.NacosPropertySourceRepository;
|
||||||
import com.alibaba.cloud.nacos.parser.NacosDataParserHandler;
|
import com.alibaba.cloud.nacos.parser.NacosDataParserHandler;
|
||||||
@ -39,7 +38,7 @@ public class NacosPropertySourceBuilder {
|
|||||||
private static final Logger log = LoggerFactory
|
private static final Logger log = LoggerFactory
|
||||||
.getLogger(NacosPropertySourceBuilder.class);
|
.getLogger(NacosPropertySourceBuilder.class);
|
||||||
|
|
||||||
private static final Properties EMPTY_PROPERTIES = new Properties();
|
private static final Map<String, Object> EMPTY_MAP = new LinkedHashMap();
|
||||||
|
|
||||||
private ConfigService configService;
|
private ConfigService configService;
|
||||||
|
|
||||||
@ -72,14 +71,15 @@ public class NacosPropertySourceBuilder {
|
|||||||
*/
|
*/
|
||||||
NacosPropertySource build(String dataId, String group, String fileExtension,
|
NacosPropertySource build(String dataId, String group, String fileExtension,
|
||||||
boolean isRefreshable) {
|
boolean isRefreshable) {
|
||||||
Properties p = loadNacosData(dataId, group, fileExtension);
|
Map<String, Object> p = loadNacosData(dataId, group, fileExtension);
|
||||||
NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId,
|
NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId,
|
||||||
propertiesToMap(p), new Date(), isRefreshable);
|
p, new Date(), isRefreshable);
|
||||||
NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);
|
NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);
|
||||||
return nacosPropertySource;
|
return nacosPropertySource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Properties loadNacosData(String dataId, String group, String fileExtension) {
|
private Map<String, Object> loadNacosData(String dataId, String group,
|
||||||
|
String fileExtension) {
|
||||||
String data = null;
|
String data = null;
|
||||||
try {
|
try {
|
||||||
data = configService.getConfig(dataId, group, timeout);
|
data = configService.getConfig(dataId, group, timeout);
|
||||||
@ -87,16 +87,16 @@ public class NacosPropertySourceBuilder {
|
|||||||
log.warn(
|
log.warn(
|
||||||
"Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]",
|
"Ignore the empty nacos configuration and get it based on dataId[{}] & group[{}]",
|
||||||
dataId, group);
|
dataId, group);
|
||||||
return EMPTY_PROPERTIES;
|
return EMPTY_MAP;
|
||||||
}
|
}
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debug(String.format(
|
log.debug(String.format(
|
||||||
"Loading nacos data, dataId: '%s', group: '%s', data: %s", dataId,
|
"Loading nacos data, dataId: '%s', group: '%s', data: %s", dataId,
|
||||||
group, data));
|
group, data));
|
||||||
}
|
}
|
||||||
Properties properties = NacosDataParserHandler.getInstance()
|
Map<String, Object> dataMap = NacosDataParserHandler.getInstance()
|
||||||
.parseNacosData(data, fileExtension);
|
.parseNacosData(data, fileExtension);
|
||||||
return properties == null ? EMPTY_PROPERTIES : properties;
|
return dataMap == null ? EMPTY_MAP : dataMap;
|
||||||
}
|
}
|
||||||
catch (NacosException e) {
|
catch (NacosException e) {
|
||||||
log.error("get data from Nacos error,dataId:{}, ", dataId, e);
|
log.error("get data from Nacos error,dataId:{}, ", dataId, e);
|
||||||
@ -104,14 +104,7 @@ public class NacosPropertySourceBuilder {
|
|||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, e);
|
log.error("parse data from Nacos error,dataId:{},data:{},", dataId, data, e);
|
||||||
}
|
}
|
||||||
return EMPTY_PROPERTIES;
|
return EMPTY_MAP;
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private Map<String, Object> propertiesToMap(Properties properties) {
|
|
||||||
Map<String, Object> result = new HashMap<>(16);
|
|
||||||
properties.forEach((k, v) -> result.put(String.valueOf(k), v));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,12 @@
|
|||||||
package com.alibaba.cloud.nacos.parser;
|
package com.alibaba.cloud.nacos.parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
@ -32,6 +35,8 @@ public abstract class AbstractNacosDataParser {
|
|||||||
|
|
||||||
protected static final String VALUE = "value";
|
protected static final String VALUE = "value";
|
||||||
|
|
||||||
|
protected static final String EMPTY_STRING = "";
|
||||||
|
|
||||||
private String extension;
|
private String extension;
|
||||||
|
|
||||||
private AbstractNacosDataParser nextParser;
|
private AbstractNacosDataParser nextParser;
|
||||||
@ -66,7 +71,7 @@ public abstract class AbstractNacosDataParser {
|
|||||||
* @return result of Properties
|
* @return result of Properties
|
||||||
* @throws IOException thrown if there is a problem parsing config.
|
* @throws IOException thrown if there is a problem parsing config.
|
||||||
*/
|
*/
|
||||||
public final Properties parseNacosData(String data, String extension)
|
public final Map<String, Object> parseNacosData(String data, String extension)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (extension == null || extension.length() < 1) {
|
if (extension == null || extension.length() < 1) {
|
||||||
throw new IllegalStateException("The file extension cannot be empty");
|
throw new IllegalStateException("The file extension cannot be empty");
|
||||||
@ -86,7 +91,7 @@ public abstract class AbstractNacosDataParser {
|
|||||||
* @return result of Properties
|
* @return result of Properties
|
||||||
* @throws IOException thrown if there is a problem parsing config.
|
* @throws IOException thrown if there is a problem parsing config.
|
||||||
*/
|
*/
|
||||||
protected abstract Properties doParse(String data) throws IOException;
|
protected abstract Map<String, Object> doParse(String data) throws IOException;
|
||||||
|
|
||||||
protected AbstractNacosDataParser setNextParser(AbstractNacosDataParser nextParser) {
|
protected AbstractNacosDataParser setNextParser(AbstractNacosDataParser nextParser) {
|
||||||
this.nextParser = nextParser;
|
this.nextParser = nextParser;
|
||||||
@ -108,23 +113,36 @@ public abstract class AbstractNacosDataParser {
|
|||||||
|| this.extension.contains(extension);
|
|| this.extension.contains(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected void flattenedMap(Map<String, Object> result, Map<String, Object> dataMap,
|
||||||
* Generate key-value pairs from the map.
|
String parentKey) {
|
||||||
*/
|
Set<Map.Entry<String, Object>> entries = dataMap.entrySet();
|
||||||
protected Properties generateProperties(Map<String, Object> map) {
|
for (Iterator<Map.Entry<String, Object>> iterator = entries.iterator(); iterator
|
||||||
if (null == map || map.isEmpty()) {
|
.hasNext();) {
|
||||||
return null;
|
Map.Entry<String, Object> entry = iterator.next();
|
||||||
}
|
|
||||||
Properties properties = new Properties();
|
|
||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
if (StringUtils.isEmpty(key)) {
|
Object value = entry.getValue();
|
||||||
|
|
||||||
|
String fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith("[")
|
||||||
|
? parentKey.concat(key) : parentKey.concat(DOT).concat(key);
|
||||||
|
|
||||||
|
if (value instanceof Map) {
|
||||||
|
Map<String, Object> map = (Map<String, Object>) value;
|
||||||
|
flattenedMap(result, map, fullKey);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
key = key.startsWith(DOT) ? key.replaceFirst("\\.", "") : key;
|
else if (value instanceof Collection) {
|
||||||
properties.put(key, entry.getValue());
|
int count = 0;
|
||||||
|
Collection<Object> collection = (Collection<Object>) value;
|
||||||
|
for (Object object : collection) {
|
||||||
|
flattenedMap(result,
|
||||||
|
Collections.singletonMap("[" + (count++) + "]", object),
|
||||||
|
fullKey);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.put(fullKey, value);
|
||||||
}
|
}
|
||||||
return properties;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,7 +152,7 @@ public abstract class AbstractNacosDataParser {
|
|||||||
if (map == null || map.isEmpty()) {
|
if (map == null || map.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Map<String, Object> result = new HashMap<>(map);
|
Map<String, Object> result = new LinkedHashMap<>(map);
|
||||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||||
String key = entry.getKey();
|
String key = entry.getKey();
|
||||||
if (key.contains(DOT)) {
|
if (key.contains(DOT)) {
|
||||||
|
@ -17,13 +17,8 @@
|
|||||||
package com.alibaba.cloud.nacos.parser;
|
package com.alibaba.cloud.nacos.parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
@ -41,12 +36,12 @@ public class NacosDataJsonParser extends AbstractNacosDataParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Properties doParse(String data) throws IOException {
|
protected Map<String, Object> doParse(String data) throws IOException {
|
||||||
if (StringUtils.isEmpty(data)) {
|
if (StringUtils.isEmpty(data)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Map<String, Object> map = parseJSON2Map(data);
|
Map<String, Object> map = parseJSON2Map(data);
|
||||||
return this.generateProperties(this.reloadMap(map));
|
return this.reloadMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,49 +50,17 @@ public class NacosDataJsonParser extends AbstractNacosDataParser {
|
|||||||
* @return the map convert by json string
|
* @return the map convert by json string
|
||||||
* @throws IOException thrown if there is a problem parsing config.
|
* @throws IOException thrown if there is a problem parsing config.
|
||||||
*/
|
*/
|
||||||
public static Map<String, Object> parseJSON2Map(String json) throws IOException {
|
private Map<String, Object> parseJSON2Map(String json) throws IOException {
|
||||||
Map<String, Object> result = new HashMap<>(32);
|
Map<String, Object> result = new LinkedHashMap<>(32);
|
||||||
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
Map<String, Object> nacosDataMap = mapper.readValue(json, Map.class);
|
Map<String, Object> nacosDataMap = mapper.readValue(json, LinkedHashMap.class);
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(nacosDataMap)) {
|
if (CollectionUtils.isEmpty(nacosDataMap)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
parseNacosDataMap(result, nacosDataMap, "");
|
flattenedMap(result, nacosDataMap, EMPTY_STRING);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseNacosDataMap(Map<String, Object> result,
|
|
||||||
Map<String, Object> dataMap, String parentKey) {
|
|
||||||
Set<Map.Entry<String, Object>> entries = dataMap.entrySet();
|
|
||||||
for (Iterator<Map.Entry<String, Object>> iterator = entries.iterator(); iterator
|
|
||||||
.hasNext();) {
|
|
||||||
Map.Entry<String, Object> entry = iterator.next();
|
|
||||||
String key = entry.getKey();
|
|
||||||
Object value = entry.getValue();
|
|
||||||
|
|
||||||
String fullKey = StringUtils.isEmpty(parentKey) ? key : key.startsWith("[")
|
|
||||||
? parentKey.concat(key) : parentKey.concat(DOT).concat(key);
|
|
||||||
|
|
||||||
if (value instanceof Map) {
|
|
||||||
Map<String, Object> map = (Map<String, Object>) value;
|
|
||||||
parseNacosDataMap(result, map, fullKey);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (value instanceof Collection) {
|
|
||||||
int count = 0;
|
|
||||||
Collection<Object> collection = (Collection<Object>) value;
|
|
||||||
for (Object object : collection) {
|
|
||||||
parseNacosDataMap(result,
|
|
||||||
Collections.singletonMap("[" + (count++) + "]", object),
|
|
||||||
fullKey);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.put(fullKey, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
package com.alibaba.cloud.nacos.parser;
|
package com.alibaba.cloud.nacos.parser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Properties;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author zkz
|
* @author zkz
|
||||||
@ -34,10 +34,11 @@ public final class NacosDataParserHandler {
|
|||||||
* Parsing nacos configuration content.
|
* Parsing nacos configuration content.
|
||||||
* @param data config from Nacos
|
* @param data config from Nacos
|
||||||
* @param extension file extension. json or xml or yml or yaml or properties
|
* @param extension file extension. json or xml or yml or yaml or properties
|
||||||
* @return result of properties
|
* @return result of LinkedHashMap
|
||||||
* @throws IOException thrown if there is a problem parsing config.
|
* @throws IOException thrown if there is a problem parsing config.
|
||||||
*/
|
*/
|
||||||
public Properties parseNacosData(String data, String extension) throws IOException {
|
public Map<String, Object> parseNacosData(String data, String extension)
|
||||||
|
throws IOException {
|
||||||
if (null == parser) {
|
if (null == parser) {
|
||||||
parser = this.createParser();
|
parser = this.createParser();
|
||||||
}
|
}
|
||||||
|
@ -16,24 +16,49 @@
|
|||||||
|
|
||||||
package com.alibaba.cloud.nacos.parser;
|
package com.alibaba.cloud.nacos.parser;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.Properties;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author zkz
|
* @author zkz
|
||||||
*/
|
*/
|
||||||
public class NacosDataPropertiesParser extends AbstractNacosDataParser {
|
public class NacosDataPropertiesParser extends AbstractNacosDataParser {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory
|
||||||
|
.getLogger(NacosDataPropertiesParser.class);
|
||||||
|
|
||||||
public NacosDataPropertiesParser() {
|
public NacosDataPropertiesParser() {
|
||||||
super("properties");
|
super("properties");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Properties doParse(String data) throws IOException {
|
protected Map<String, Object> doParse(String data) throws IOException {
|
||||||
Properties properties = new Properties();
|
Map<String, Object> result = new LinkedHashMap<>();
|
||||||
properties.load(new StringReader(data));
|
|
||||||
return properties;
|
try (BufferedReader reader = new BufferedReader(new StringReader(data))) {
|
||||||
|
for (String line = reader.readLine(); line != null; line = reader
|
||||||
|
.readLine()) {
|
||||||
|
String dataLine = line.trim();
|
||||||
|
if (StringUtils.isEmpty(dataLine) || dataLine.startsWith("#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int index = dataLine.indexOf("=");
|
||||||
|
if (index == -1) {
|
||||||
|
log.warn("the config data is invalid {}", dataLine);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.put(dataLine.substring(0, index), dataLine.substring(index + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,8 @@ package com.alibaba.cloud.nacos.parser;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
@ -46,17 +45,17 @@ public class NacosDataXmlParser extends AbstractNacosDataParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Properties doParse(String data) throws IOException {
|
protected Map<String, Object> doParse(String data) throws IOException {
|
||||||
if (StringUtils.isEmpty(data)) {
|
if (StringUtils.isEmpty(data)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Map<String, Object> map = parseXml2Map(data);
|
Map<String, Object> map = parseXml2Map(data);
|
||||||
return this.generateProperties(this.reloadMap(map));
|
return this.reloadMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Object> parseXml2Map(String xml) throws IOException {
|
private Map<String, Object> parseXml2Map(String xml) throws IOException {
|
||||||
xml = xml.replaceAll("\\r", "").replaceAll("\\n", "").replaceAll("\\t", "");
|
xml = xml.replaceAll("\\r", "").replaceAll("\\n", "").replaceAll("\\t", "");
|
||||||
Map<String, Object> map = new HashMap<>(32);
|
Map<String, Object> map = new LinkedHashMap<>(32);
|
||||||
try {
|
try {
|
||||||
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
|
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance()
|
||||||
.newDocumentBuilder();
|
.newDocumentBuilder();
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
package com.alibaba.cloud.nacos.parser;
|
package com.alibaba.cloud.nacos.parser;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
import org.springframework.beans.factory.config.YamlMapFactoryBean;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,10 +32,13 @@ public class NacosDataYamlParser extends AbstractNacosDataParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Properties doParse(String data) {
|
protected Map<String, Object> doParse(String data) {
|
||||||
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
|
YamlMapFactoryBean yamlFactory = new YamlMapFactoryBean();
|
||||||
yamlFactory.setResources(new ByteArrayResource(data.getBytes()));
|
yamlFactory.setResources(new ByteArrayResource(data.getBytes()));
|
||||||
return yamlFactory.getObject();
|
|
||||||
|
Map<String, Object> result = new LinkedHashMap<>();
|
||||||
|
flattenedMap(result, yamlFactory.getObject(), EMPTY_STRING);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user