【思路】使用Java手写入参是 Json对象,根据json对象中type值不同,选择不同规则链的自定义规则节点的支持过滤、支持分支的规则引擎案例
- 工作小总结
- 时间:2023-04-20 11:35
- 2548人已阅读
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
正在为您搜索: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 方法,以便其他代码可以自由地配置它们。