fix nacos load data

pull/1179/head
yuhuangbin 5 years ago
parent 648944df09
commit 26741dc799

@ -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;
}
else if (value instanceof Collection) {
int count = 0;
Collection<Object> collection = (Collection<Object>) value;
for (Object object : collection) {
flattenedMap(result,
Collections.singletonMap("[" + (count++) + "]", object),
fullKey);
}
continue; continue;
} }
key = key.startsWith(DOT) ? key.replaceFirst("\\.", "") : key;
properties.put(key, entry.getValue()); 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…
Cancel
Save