【思路】使用Java手写入参是 Json对象,根据json对象中type值不同,选择不同规则链的自定义规则节点的支持过滤、支持分支的规则引擎案例
- 工作小总结
- 时间:2023-04-20 11:35
- 2858人已阅读
🔔🔔好消息!好消息!🔔🔔
有需要的朋友👉:微信号
正在为您搜索:Java、手写、Json对象、type值
这是一个相对复杂的案例,但是我会尽力解释。首先,我们需要考虑如何定义规则节点。在这个案例中,规则节点应该包含以下属性:
节点名称
条件:一些表达式,用于表示当这些条件为真时,规则应该被触发。
动作:当规则被触发时应该执行的操作,可以是输出日志、发送邮件等。
然后,我们需要定义规则链,它由多个规则节点连接而成。规则链应该有一个入口(也就是第一个规则节点),并且每个规则节点应该有他们的后继节点。
这里需要注意的是,规则节点和规则链应该是可以动态配置的。例如,某些规则节点可能不再适用于当前场景,需要从规则链中删除。另外,新的规则节点也应该可以被添加到规则链中。
在这个案例中,我们还需要根据输入的 JSON 对象来选择适当的规则链。例如,如果 JSON 对象中的 type 值为 "A",则应该选择规则链 A,否则选择规则链 B。
下面是一个简单的 Java 代码实现,实现了上述的要求:
java
public class Rule {
private String name; // 规则名称
private List<Expression> conditions; // 条件列表
private Action action; // 规则动作
public Rule(String name, List<Expression> conditions, Action action) {
this.name = name;
this.conditions = conditions;
this.action = action;
}
// 以下是 getter 和 setter 方法
// ...
}
public class RuleChain {
private List<RuleNode> ruleNodes; // 规则节点列表
private Map<String, RuleNode> ruleNodeMap; // 规则节点名称 -> 规则节点
public RuleChain() {
this.ruleNodes = new ArrayList<>();
this.ruleNodeMap = new HashMap<>();
}
public void addNode(RuleNode ruleNode) {
this.ruleNodes.add(ruleNode);
this.ruleNodeMap.put(ruleNode.getName(), ruleNode);
}
public RuleNode getEntryNode() {
return this.ruleNodes.get(0);
}
public RuleNode getNodeByName(String name) {
return this.ruleNodeMap.get(name);
}
// getter 和 setter 方法
// ...
}
public class RuleNode {
private String name; // 规则节点名称
private List<Expression> conditions; // 条件列表
private List<String> nextNodeNames; // 后继节点名称列表
private Action action; // 规则动作
public RuleNode(String name, List<Expression> conditions, List<String> nextNodeNames, Action action) {
this.name = name;
this.conditions = conditions;
this.nextNodeNames = nextNodeNames;
this.action = action;
}
// 以下是 getter 和 setter 方法
// ...
}
public class FilterRuleEngine {
private Map<String, RuleChain> ruleChains;
public FilterRuleEngine() {
this.ruleChains = new HashMap<>();
}
public void addRuleChain(String type, RuleChain ruleChain) {
this.ruleChains.put(type, ruleChain);
}
public List<Action> evaluate(JSONObject obj) {
String type = obj.getString("type");
RuleChain ruleChain = this.ruleChains.get(type);
if (ruleChain == null) {
return Collections.emptyList();
}
Facts facts = new Facts(obj);
RuleNode currentNode = ruleChain.getEntryNode();
List<Action> actions = new ArrayList<>();
while (currentNode != null) {
if (ruleApplies(currentNode, facts)) {
if (currentNode.getAction() != null) {
actions.add(currentNode.getAction());
}
String nextNodeName = getNodeToExecute(currentNode, facts);
if (nextNodeName == null) {
break;
}
currentNode = ruleChain.getNodeByName(nextNodeName);
} else {
currentNode = null;
}
}
return actions;
}
private boolean ruleApplies(RuleNode node, Facts facts) {
boolean result = true;
for (Expression condition : node.getConditions()) {
result = result && condition.evaluate(facts);
}
return result;
}
private String getNodeToExecute(RuleNode node, Facts facts) {
for (String nextNodeName : node.getNextNodeNames()) {
RuleNode nextNode = node.getParent().getNodeByName(nextNodeName);
if (ruleApplies(nextNode, facts)) {
return nextNode.getName();
}
}
return null;
}
}
public class Facts {
private JSONObject obj;
public Facts(JSONObject obj) {
this.obj = obj;
}
public Object get(String name) {
return this.obj.get(name);
}
}这里我们使用 JSONObject 类,来表示输入的 JSON 对象。Facts 类则封装了 JSONObject 对象,使得我们可以像之前一样使用 get() 方法来获取属性值。行为类的定义与之前一样,没有变化。
在 FilterRuleEngine 类中,我们新增了一个 ruleChains 字段,用于存放不同类型规则链的映射关系。在 addRuleChain() 方法中,我们可以将不同类型规则链添加到这个映射关系中。在 evaluate() 方法中,我们根据输入的 JSON 对象中的 type 值来选择适当的规则链,如果没有找到则返回一个空列表。
接下来,在evaluate()方法中,我们创建了一个Facts对象,用于向规则节点提供条件所需要的数据。然后,我们获取规则链的入口节点,并且循环遍历规则链中的所有节点,依次评估它们的条件并执行相应的操作。当我们遇到没有匹配的后继节点时,我们退出循环并返回所有收集到的操作(如果有)。
最后,我们还需要为规则节点和规则链提供 getter 和 setter 方法,以便其他代码可以自由地配置它们。