需求描述
在开发过程中,会遇到通过界面添加指标,然后指标嵌套添加 or 或者 and,比较符 >= <= ==
!= 等,使用前端插件,直接生成二叉树结构的json串,保存起来,然后通过该json串,计算是否有对应的指标达到规则,然后进行报警预警等。
实现
1、生成的json串
例如:
{
"relation": "and",
"firstRule": {
"relation": "and",
"firstRule": {
"value": "10",
"operator": ">=",
"ruleName": "A1"
},
"secondRule": {
"value": "20",
"operator": "==",
"ruleName": "B1"
}
},
"secondRule": {
"relation": "and",
"firstRule": {
"relation": "and",
"firstRule": {
"value": "10",
"operator": ">=",
"ruleName": "A21"
},
"secondRule": {
"value": "20",
"operator": "==",
"ruleName": "A22"
}
},
"secondRule": {
"relation": "and",
"firstRule": {
"value": "10",
"operator": ">=",
"ruleName": "B21"
},
"secondRule": {
"value": "20",
"operator": "==",
"ruleName": "B22"
}
}
}
}
2、在java中创建对象,将json串转为java对象
Java对象:
@Data
public class CombinationRule {
private CombinationRule firstRule;
private String relation;
private CombinationRule secondRule;
private String ruleName;
private String operator;
private Double value;
}
将json串转为对象
//定义一个typeReference 全局实例对象
private final TypeReference<CombinationRule> typeReference = new TypeReference<CombinationRule>() {
};
ObjectMapper objectMapper = new ObjectMapper();
//读取json,将json转为之前定义的对象,发现就是一颗二叉树,读取的对象为root节点
root = objectMapper.readValue(moduleAlarmManagement.getAlarmRule(), this.typeReference);
3、解析二叉树,采用中序遍历,左子树开始遍历时添加左括号,右子树遍历结束时,添加右括弧,根节点不添加,叶子节点自行组织结构
例如上述json转为规则后的结果:
((yy>=10.0)and(ty>=20.0))and(((scty>=10.0)or(jkyl=20.0))and((jkhy>=10.0)and(jkwd=20.0)))
叶子节点也需要添加括弧,在遍历到叶子节点时,直接拼接就可以
解析代码:
//参数传入了root节点,为了获取到解析后的规则,传入一个StringBuilder ,传入节点深度,根节点为1,递归遍历
private void preNode(CombinationRule combinationRule, StringBuilder rule, StringBuilder ruleNames, Integer deep){
if(Objects.isNull(combinationRule)){
return;
}
//叶子节点
else if(Objects.isNull(combinationRule.getFirstRule()) && Objects.isNull(combinationRule.getSecondRule())){
String operation;
if(Objects.equals(combinationRule.getOperator(), "==")){
operation = "=";
}else {
operation = combinationRule.getOperator();
}
rule.append("(").append(PingYinUtil.getPinYinHeadChar(combinationRule.getRuleName()))
.append(operation).append(combinationRule.getValue()).append(")");
ruleNames.append(combinationRule.getRuleName()).append(",");
}else {
if(deep > 1){
rule.append("(");
}
if(Objects.nonNull(combinationRule.getFirstRule())){
CombinationRule first = combinationRule.getFirstRule();
preNode(first, rule, ruleNames, deep+1);
}
if(Objects.nonNull(combinationRule.getRelation())){
rule.append(combinationRule.getRelation());
}
if(Objects.nonNull(combinationRule.getSecondRule())){
CombinationRule second = combinationRule.getSecondRule();
preNode(second, rule, ruleNames, deep+1);
}
if(deep > 1){
rule.append(")");
}
}
4、最终实现了json转为数结构,然后树结构转为可以直接进行sql查询的规则