背景
项目需要对接Skywalking,使用nacos动态配置Skywalking告警配置alarm-settings.yml, 所以需要用的yaml相关工具, 这里使用Jackson yaml,也就是jackson-dataformat-yaml,版本2.16.6
使用alarm-settings.yml中的一段进行测试,在项目端生成类似的yaml文件
第一次尝试:全部默认配置
通过查阅资料,很简单,编写后运行
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Test5 {
public static void main(String[] args) {
Map<String, Object> yaml = new HashMap<>();
Map<String, Object> rules = new HashMap<>();
rules.put("service_instance_resp_time_rule", "sum(service_instance_resp_time > 1000) >= 2");
rules.put("period", 10);
rules.put("silence-period", 5);
rules.put("message", "Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes");
yaml.put("rules", rules);
// 将Java对象写入YAML文件
try {
ObjectMapper objectMapper = new ObjectMapper(
new YAMLFactory()
);
System.out.println("YAML生成。");
String bbb = objectMapper.writeValueAsString(yaml);
System.out.println(bbb);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果如下,
但是出现问题,
1,开头出现"---"
2,message属性哪里,出现换行
3,字符串带了"",正常.
这肯定不行,还得进行修改,应该有配置的参数
第二次尝试:开启,关闭一些特性
查找相关帖子后,发现可以关闭或开启一些特性, 这些特性是YAMLGenerator.Feature枚举,了解后,进行代码改进,具体如下
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Test51 {
public static void main(String[] args) {
Map<String, Object> yaml = new HashMap<>();
Map<String, Object> rules = new HashMap<>();
rules.put("service_instance_resp_time_rule", "sum(service_instance_resp_time > 1000) >= 2");
rules.put("period", 10);
rules.put("silence-period", 5);
rules.put("message", "Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes");
yaml.put("rules", rules);
// 将Java对象写入YAML文件
try {
ObjectMapper objectMapper = new ObjectMapper(
new YAMLFactory()
//禁用开头标识---
.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
//自动拆分多行
.disable(YAMLGenerator.Feature.SPLIT_LINES)
//去掉引号
.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)
);
System.out.println("YAML生成。");
String bbb = objectMapper.writeValueAsString(yaml);
System.out.println(bbb);
} catch (IOException e) {
e.printStackTrace();
}
}
}
即:
WRITE_DOC_START_MARKER:禁用文档开头标记,也就是---
SPLIT_LINES:禁用拆分多行
MINIMIZE_QUOTES:开启尽量减少双引号,
运行结果如下:
虽然3问题都改进2个,但是massge那个双引号还是存在, 经过一番查找,没有找到相关的特性开关,这也是网上大部分提供的方法,无奈之下只能debug查看源码看看有没有什么方法,结果还真有,开心,哈哈哈
第三次尝试:重写StringQuotingChecker
通过debug第二尝试代码,发现MINIMIZE_QUOTES特性的配置生效代码在YAMLGenerator.java 579行,writeString方法中,片段如下
第597行判断中,有一句"_quotingChecker.needToQuoteValue(text)"是ture,导致结果添加了双引号,查看里面代码,_quotingChecker的实例是StringQuotingChecker.Default, 继续调试
发现是,"valueHasQuotableChar(value)"这句的结果,继续往下,发现是StringQuotingChecker.valueHasQuotableChar方法的原因,
这里面就很明显,也就是说,字符串中带有诸如特殊字符[]{}这些,判断是字符串,强制添加双引号.
总结下来,避开valueHasQuotableChar(value)即可以得到想要的结果,不判断特殊字符都去掉双引号,最后修改代码如下:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.dataformat.yaml.util.StringQuotingChecker;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class Test52 {
public static void main(String[] args) {
Map<String, Object> yaml = new HashMap<>();
Map<String, Object> rules = new HashMap<>();
rules.put("service_instance_resp_time_rule", "sum(service_instance_resp_time > 1000) >= 2");
rules.put("period", 10);
rules.put("silence-period", 5);
rules.put("message", "Response time of service instance {name} is more than 1000ms in 2 minutes of last 10 minutes");
yaml.put("rules", rules);
// 将Java对象写入YAML文件
try {
ObjectMapper objectMapper = new ObjectMapper(
YAMLFactory.builder()
.stringQuotingChecker(new StringQuotingChecker() {
@Override
public boolean needToQuoteName(String name) {
return isReservedKeyword(name) || looksLikeYAMLNumber(name);
}
@Override
public boolean needToQuoteValue(String value) {
// return isReservedKeyword(value) || valueHasQuotableChar(value);
return isReservedKeyword(value);
}
})
.build()
//禁用开头标识---
.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
//自动拆分多行
.disable(YAMLGenerator.Feature.SPLIT_LINES)
//去掉引号:另外,需要像上面重写StringQuotingChecker,否则会因为Skywalking配置文件中,因为存在"{","}"等特殊字符而还是会包裹双引号
.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES)
);
System.out.println("YAML生成。");
String bbb = objectMapper.writeValueAsString(yaml);
System.out.println(bbb);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
这会总算完成了.