多环境配置文件管理,增加一个配置属性,多套环境配置文件需同时增加,如果忘记了,那么就报错。对多环境配置文件进行管理,使用yaml作为文件时,就涉及到yaml的一些解析,修改,新增操作。
java管理yaml
- 1. 环境依赖
- 2. snakeyaml方法简单介绍
- 3. yaml处理思路
- 4. yaml字符串转非嵌套Map对象
- 5. List对象转嵌套yaml对象
- 6. 新旧yaml对比,yaml新增,删除属性
- 7.新增属性属性值不为空
1. 环境依赖
首先需要依赖snakeyaml,这里使用的是1.23版本
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.23</version>
</dependency>
2. snakeyaml方法简单介绍
加载yaml对象:
< T > T - loadAs(String,Class) :加载yaml对象,返回Class对象
< T > Object - load(String):加载yaml对象,返回object对象
iterable < object > - loadAll(String):加载yaml对象,返回迭代器
对象转为字符:
String dump(object):object转化为字符串对象(只转化最外层yaml节点)
String dumpAsMap(Map):Map对象转化为字符串对象
String content = "nacos:\n" +
" dg: 889990\n" +
" addd: 444\n" +
" ggggg:\n" +
" aaaa: ''\n" +
"spring:\n" +
" redis:\n" +
" path: 3344\n" +
"ooo:\n" +
" pp: ''\n";
Yaml yaml = new Yaml();
Map map = yaml.loadAs(content, Map.class);
System.out.println(map);
Object load = yaml.load(content);
System.out.println(load);
Iterable<Object> objects = yaml.loadAll(content);
for (Iterator<Object> it = objects.iterator(); it.hasNext();){
Map<String,Object> object = (Map<String, Object>) it.next();
System.out.println(object);
}
String dump = yaml.dump(map);
System.out.println(dump);
String s = yaml.dumpAsMap(map);
System.out.println(s);
3. yaml处理思路
snakeyaml解析获取到的Map集合是嵌套集合,{redis={host=6379,url=xxx}},这样的结构去做配置信息的变更比对是不方便的。
因此先将此数据类型,转化为非嵌套Map集合,即{=6379,=xxx}的数据格式(Spring @value注解取值时,也是这种数据结构,IOC容器加载时,对配置文件进行解析,也是解析成这种格式)。
解析为以上格式之后,再去对新旧配置进行节点的新增,删除判断就容易多了,提取以上Map集合的Key值放入List集合中,使用List集合的差集方法,即可得到新旧配置的差异对象。
得到差异对象后,再将List对象使用Map容器承装(Map嵌套容器),将变更对象与原嵌套对象进行合并,再转化为yaml字符串,之后该输出到文件输出到文件,该存储就存储。
4. yaml字符串转非嵌套Map对象
输出结果:{=, =889990, =3344, =, =444}
private static final Map<String,String> cacheYamlMap = new HashMap<>();
public static void main(String[] args) {
String content = "nacos:\n" +
" dg: 889990\n" +
" addd: 444\n" +
" ggggg:\n" +
" aaaa: ''\n" +
"spring:\n" +
" redis:\n" +
" path: 3344\n" +
"ooo:\n" +
" pp: ''\n";
Yaml yaml = new Yaml();
Iterable<Object> oldYaml = yaml.loadAll(content);
analyzeYamlToList(oldYaml);
System.out.println(cacheYamlMap);
}
public static void analyzeYamlToList(Iterable<Object> newYaml){
for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
Map<String,Object> object = (Map<String, Object>) it.next();
parseYamlToMap(object,null);
}
}
public static void parseYamlToMap(Map<String, Object> item, String key){
item.forEach((k,v) -> {
if(Objects.isNull(v))
if (key == null)
cacheYamlMap.put(k, "");
else
cacheYamlMap.put(key.concat(".").concat(k), "");
else if (v instanceof LinkedHashMap)
if (key == null)
parseYamlToMap((Map<String, Object>) v,k);
else
parseYamlToMap((Map<String, Object>) v,key.concat(".").concat(k));
else
if (key == null)
cacheYamlMap.put(k, v.toString());
else
cacheYamlMap.put(key.concat(".").concat(k), v.toString());
});
}
5. List对象转嵌套yaml对象
输出结果:{redis={host={name=}, aaa={bbb=}}, nacos={server={name=}}}
public static void main(String[] args) {
List<String> yaml = new ArrayList<>();
yaml.add("");
yaml.add("");
yaml.add("");
yaml.add("");
Object map = transListToLinkMap(yaml);
System.out.println(map);
}
public static Object transListToLinkMap(List<String> yamlKey){
Map<String,Object> linkMap = new LinkedHashMap();
for (String val: yamlKey ) {
Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(val);
addYamlMap(linkMap,map);
}
return linkMap;
}
private static Object transStringToLinkMap(String val){
int i = val.indexOf(".");
if(i < 0){
Map<String,Object> map = new LinkedHashMap<>();
map.put(val,"");
return map;
}
String key = val.substring(0, i);
String value = val.substring(i + 1);
Map<String ,Object> linkedHashMap = (Map<String, Object>) transStringToLinkMap(value);
Map<String,Object> map = new LinkedHashMap<>();
map.put(key,linkedHashMap);
return map;
}
public static void addYamlMap(Map<String, Object> originMap, Map<String, Object> addMap){
for (Map.Entry<String,Object> val : addMap.entrySet()) {
boolean common = false;
for (Map.Entry<String,Object> obj : originMap.entrySet()) {
if (val.getKey().equals(obj.getKey())){
common = true;
try {
Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
Map<String,Object> addVal = (Map<String,Object>) val.getValue();
addYamlMap(objVal,addVal);
}catch (Exception e){
break;
}
break;
}
}
if(!common){
originMap.put(val.getKey(),val.getValue());
}
}
}
6. 新旧yaml对比,yaml新增,删除属性
懒得一个个demo贴了,下面贴出我写的yamlUtil类,需要什么功能*组合。
以下yaml属性新增的时候,默认值是""空字符串,未设默认值,需要默认值自行修改。
private static final Map<String,String> cacheYamlMap = new HashMap<>();
public enum ConstantEnum{
ADD("add"),
REMOVE("remove");
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
ConstantEnum(String code){
this.code = code;
}
public static ConstantEnum getInstance(String code){
for (ConstantEnum constantEnum: values()) {
if(constantEnum.getCode().equals(code)){
return constantEnum;
}
}
return null;
}
}
public static void main(String[] args) {
//加两个attr节点下属性,删addd属性
String oldContent = "nacos:\n" +
" dg: 889990\n" +
" addd: 444\n" +
"spring:\n" +
" redis:\n" +
" path: 3344\n";
String newContent = "nacos:\n" +
" dg: 889990\n" +
"spring:\n" +
" redis:\n" +
" path: 3344\n" +
" attr:\n" +
" name: 3333\n" +
" value: 4444";
Yaml yaml = new Yaml();
List<String> addAttr = YamlParserUtil.compareAndGetDiffAttr(oldContent, newContent, YamlParserUtil.ConstantEnum.ADD);
List<String> removeAttr = YamlParserUtil.compareAndGetDiffAttr(oldContent, newContent, YamlParserUtil.ConstantEnum.REMOVE);
Map<String,Object> addMap = (Map<String, Object>) YamlParserUtil.transListToLinkMap(addAttr);
Map<String,Object> removeMap = (Map<String, Object>) YamlParserUtil.transListToLinkMap(removeAttr);
Map originMap = yaml.loadAs(oldContent, Map.class);
YamlParserUtil.addAndRemoveYaml(originMap,removeMap,addMap);
String dump = yaml.dumpAsMap(originMap);
System.out.println(dump);
}
/**
* trans key list to map
* demo: to {spring={redis={host=}}}
* @param yamlKey
* @return
*/
public static Object transListToLinkMap(List<String> yamlKey){
Map<String,Object> linkMap = new LinkedHashMap();
for (String val: yamlKey ) {
Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(val);
addYamlMap(linkMap,map);
}
return linkMap;
}
public static void addAndRemoveYaml(Map<String,Object> originMap,Map<String,Object> removeMap,Map<String,Object> addMap){
removeYamlMap(originMap,removeMap);
addYamlMap(originMap,addMap);
}
public static boolean removeYamlMap(Map<String, Object> originMap, Map<String, Object> removeMap){
for (Map.Entry<String,Object> val : removeMap.entrySet()) {
for (Map.Entry<String,Object> obj :originMap.entrySet()) {
if(val.getKey().equals(obj.getKey())){
try {
Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
Map<String,Object> addVal = (Map<String,Object>) val.getValue();
if(removeYamlMap(objVal,addVal)){
originMap.remove(val.getKey());
break;
}
}catch (Exception e){
originMap.remove(val.getKey());
break;
}
}
}
}
if(originMap==null || originMap.isEmpty()){
return true;
}
return false;
}
/**
* {spring={redis={host=}}} | {spring={rabbit={host=}}} merge to {spring={redis={host=},rabbit={host=}}}
*
* Combine the addMap collection, do not allow the same key value to be overwritten
* @param originMap
* @param addMap
*/
public static void addYamlMap(Map<String, Object> originMap, Map<String, Object> addMap){
for (Map.Entry<String,Object> val : addMap.entrySet()) {
boolean common = false;
for (Map.Entry<String,Object> obj : originMap.entrySet()) {
if (val.getKey().equals(obj.getKey())){
common = true;
try {
Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
Map<String,Object> addVal = (Map<String,Object>) val.getValue();
addYamlMap(objVal,addVal);
}catch (Exception e){
break;
}
break;
}
}
if(!common){
originMap.put(val.getKey(),val.getValue());
}
}
}
/**
* to {spring={redis={host=}}}
*
* trans string to map,Parse the yaml string
* @param val
* @return
*/
private static Object transStringToLinkMap(String val){
int i = val.indexOf(".");
if(i < 0){
Map<String,Object> map = new LinkedHashMap<>();
map.put(val,"");
return map;
}
String key = val.substring(0, i);
String value = val.substring(i + 1);
Map<String ,Object> linkedHashMap = (Map<String, Object>) transStringToLinkMap(value);
Map<String,Object> map = new LinkedHashMap<>();
map.put(key,linkedHashMap);
return map;
}
/**
*
* compare yaml content get diff key list
* @param oldContent
* @param newContent
* @return
*/
public static List<String> compareAndGetDiffAttr(String oldContent, String newContent,ConstantEnum type){
Yaml yaml = new Yaml();
Iterable<Object> oldYaml = yaml.loadAll(oldContent);
List<String> oldKey = analyzeYamlToList(oldYaml);
Iterable<Object> newYaml = yaml.loadAll(newContent);
List<String> recent = analyzeYamlToList(newYaml);
if(ConstantEnum.ADD.equals(type)){
List<String> compareList = new ArrayList<>(recent);
compareList.removeAll(oldKey);
return compareList;
}else{
List<String> compareList = new ArrayList<>(oldKey);
compareList.removeAll(recent);
return compareList;
}
}
public static List<String> analyzeYamlToList(Iterable<Object> newYaml){
for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
Map<String,Object> object = (Map<String, Object>) it.next();
parseYamlToMap(object,null);
}
List<String> keyList = new ArrayList<>();
cacheYamlMap.forEach((key,val)->{ keyList.add(key); });
cacheYamlMap.clear();
return keyList;
}
/**
* {spring={redis={host=},rabbit={host=}}} to {= ,=}
*
* trans yaml map to key map
* @param item
* @param key
*/
public static void parseYamlToMap(Map<String, Object> item, String key){
item.forEach((k,v) -> {
if(Objects.isNull(v))
if (key == null)
cacheYamlMap.put(k, "");
else
cacheYamlMap.put(key.concat(".").concat(k), "");
else if (v instanceof LinkedHashMap)
if (key == null)
parseYamlToMap((Map<String, Object>) v,k);
else
parseYamlToMap((Map<String, Object>) v,key.concat(".").concat(k));
else
if (key == null)
cacheYamlMap.put(k, v.toString());
else
cacheYamlMap.put(key.concat(".").concat(k), v.toString());
});
}
7.新增属性属性值不为空
不同的业务需求,面向的yaml对象不一样,要的效果不一样,下面的代码对比标题6,做了一些变动,以及注释,各位看官可在次基础上*发挥。(6的升级版本)
private static final Map<String,String> cacheYamlMap = new HashMap<>();
public enum ConstantEnum{
ADD("add"),
REMOVE("remove");
private String code;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
ConstantEnum(String code){
this.code = code;
}
public static ConstantEnum getInstance(String code){
for (ConstantEnum constantEnum: values()) {
if(constantEnum.getCode().equals(code)){
return constantEnum;
}
}
return null;
}
}
public static void main(String[] args) {
//加两个attr节点下属性,删addd属性
String oldContent = "nacos:\n" +
" dg: 889990\n" +
" addd: 444\n" +
"spring:\n" +
" redis:\n" +
" path: 3344\n";
String newContent = "nacos:\n" +
" dg: 889333333990\n" +
"spring:\n" +
" redis:\n" +
" path: 3344\n" +
" attr:\n" +
" name: 3333\n" +
" value: 4444";
Yaml yaml = new Yaml();
//以就模板为基准模板,对比新模板,筛选出新增的属性
List<Map<String, String>> addAttr = compareAndGetDiffAttr(oldContent, newContent, ConstantEnum.ADD);
//以旧模板为基准模板,对比新模板,筛选删除属性
List<String> removeAttr = compareAndGetDiffAttr(oldContent, newContent, ConstantEnum.REMOVE);
//将筛选出的属性集合,转化为linkMap格式
Map<String,Object> addMap = (Map<String, Object>) transMapListToLinkMap(addAttr);
Map<String,Object> removeMap = (Map<String, Object>) transListToLinkMap(removeAttr);
//以旧模板值为标准值,除了增加的属性值,其他均为旧模板值
Map originMap = yaml.loadAs(oldContent, Map.class);
//对旧模板进行新增,删除属性操作
addAndRemoveYaml(originMap,removeMap,addMap);
String dump = yaml.dumpAsMap(originMap);
System.out.println(dump);
}
/**
* trans key list to map
* demo: to {spring={redis={host=}}}
* @param yamlKey
* @return
*/
public static Object transListToLinkMap(List<String> yamlKey){
Map<String,Object> linkMap = new LinkedHashMap();
for (String val: yamlKey ) {
Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(val,null);
addYamlMap(linkMap,map);
}
return linkMap;
}
public static Object transMapListToLinkMap(List<Map<String, String>> yamlKey){
Map<String,Object> linkMap = new LinkedHashMap();
for (Map<String, String> val: yamlKey ) {
for (Map.Entry<String,String> value :val.entrySet()) {
Map<String,Object> map = (Map<String, Object>) transStringToLinkMap(value.getKey(),value.getValue());
addYamlMap(linkMap,map);
}
}
return linkMap;
}
public static void addAndRemoveYaml(Map<String,Object> originMap,Map<String,Object> removeMap,Map<String,Object> addMap){
removeYamlMap(originMap,removeMap);
addYamlMap(originMap,addMap);
}
public static boolean removeYamlMap(Map<String, Object> originMap, Map<String, Object> removeMap){
for (Map.Entry<String,Object> val : removeMap.entrySet()) {
for (Map.Entry<String,Object> obj :originMap.entrySet()) {
if(val.getKey().equals(obj.getKey())){
try {
Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
Map<String,Object> addVal = (Map<String,Object>) val.getValue();
if(removeYamlMap(objVal,addVal)){
originMap.remove(val.getKey());
break;
}
}catch (Exception e){
originMap.remove(val.getKey());
break;
}
}
}
}
if(originMap==null || originMap.isEmpty()){
return true;
}
return false;
}
/**
* {spring={redis={host=}}} | {spring={rabbit={host=}}} merge to {spring={redis={host=},rabbit={host=}}}
*
* Combine the addMap collection, do not allow the same key value to be overwritten
* @param originMap
* @param addMap
*/
public static void addYamlMap(Map<String, Object> originMap, Map<String, Object> addMap){
//遍历新旧两个嵌套集合,将值,属性进行合并
for (Map.Entry<String,Object> val : addMap.entrySet()) {
boolean common = false;
for (Map.Entry<String,Object> obj : originMap.entrySet()) {
if (val.getKey().equals(obj.getKey())){
common = true;
try {
Map<String,Object> objVal = (Map<String,Object>) obj.getValue();
Map<String,Object> addVal = (Map<String,Object>) val.getValue();
addYamlMap(objVal,addVal);
}catch (Exception e){
break;
}
break;
}
}
if(!common){
originMap.put(val.getKey(),val.getValue());
}
}
}
/**
* to {spring={redis={host=}}}
*
* trans string to map,Parse the yaml string
* @param val
* @return
*/
private static Object transStringToLinkMap(String yamlKey,String val){
int i = yamlKey.indexOf(".");
if(i < 0){
Map<String,Object> map = new LinkedHashMap<>();
map.put(yamlKey,val);
return map;
}
String key = yamlKey.substring(0, i);
String value = yamlKey.substring(i + 1);
Map<String ,Object> linkedHashMap = (Map<String, Object>) transStringToLinkMap(value,val);
Map<String,Object> map = new LinkedHashMap<>();
map.put(key,linkedHashMap);
return map;
}
/**
*
* compare yaml content get diff key list
* @param oldContent
* @param newContent
* @return
*/
public static List compareAndGetDiffAttr(String oldContent, String newContent,ConstantEnum type){
Yaml yaml = new Yaml();
//获取旧模板的key集合
Iterable<Object> oldYaml = yaml.loadAll(oldContent);
List<String> oldKey = analyzeYamlToList(oldYaml);
Iterable<Object> newYaml = yaml.loadAll(newContent);
//新增比较特殊,需要保留原值,
if(ConstantEnum.ADD.equals(type)){
//获取新模板的Key value集合
List<Map<String, String>> list = analyzeYamlToListMap(newYaml);
Iterator<Map<String, String>> iterator = list.iterator();
//遍历,与旧模板进行对比,删除掉相同key的元素,留下的就是新增的
while (iterator.hasNext()){
//以新模板为基准对比
for (Map.Entry<String,String> value :iterator.next().entrySet()) {
for (String key :oldKey) {
if(key.equals(value.getKey())){
iterator.remove();
break;
}
}
}
}
return list;
}else{
//旧模板与新模板进行取差集,得到旧模板与新模板的差异属性,即需要删除的属性
List<String> recent = analyzeYamlToList(newYaml);
//以旧模板为基准
List<String> compareList = new ArrayList<>(oldKey);
compareList.removeAll(recent);
return compareList;
}
}
public static List<String> analyzeYamlToList(Iterable<Object> newYaml){
//将yaml遍历器中的嵌套集合转化为单个KEY VALUE对应的Map集合,存放至静态变量
for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
Map<String,Object> object = (Map<String, Object>) it.next();
parseYamlToMap(object,null);
}
//将上一个步骤存放的集Map集合提取成List集合,提取单个Key值
List<String> keyList = new ArrayList<>();
cacheYamlMap.forEach((key,val)->{ keyList.add(key); });
cacheYamlMap.clear();
return keyList;
}
public static List<Map<String,String>> analyzeYamlToListMap(Iterable<Object> newYaml){
//将yaml遍历器中的嵌套集合转化为单个KEY VALUE对应的Map集合,存放至静态变量
for (Iterator<Object> it = newYaml.iterator(); it.hasNext();){
Map<String,Object> object = (Map<String, Object>) it.next();
parseYamlToMap(object,null);
}
//将上一个步骤存放的集Map集合提取成List集合,并且拆分为单个Map,放入集合(便于后续便利)
List<Map<String,String>> keyList = new ArrayList<>();
cacheYamlMap.forEach((key,val)->{
Map<String,String> map = new HashMap<>();
map.put(key,val);
keyList.add(map);
});
cacheYamlMap.clear();
return keyList;
}
/**
* {spring={redis={host=},rabbit={host=}}} to {= ,=}
*
* trans yaml map to key map
* @param item
* @param key
*/
public static void parseYamlToMap(Map<String, Object> item, String key){
//将嵌套Map集合,转化为单个Key value对应的属性集合
item.forEach((k,v) -> {
if(Objects.isNull(v))
if (key == null)
cacheYamlMap.put(k, "");
else
cacheYamlMap.put(key.concat(".").concat(k), v.toString());
else if (v instanceof LinkedHashMap)
if (key == null)
parseYamlToMap((Map<String, Object>) v,k);
else
parseYamlToMap((Map<String, Object>) v,key.concat(".").concat(k));
else
if (key == null)
cacheYamlMap.put(k, v.toString());
else
cacheYamlMap.put(key.concat(".").concat(k), v.toString());
});
}