easy rule 学习记录

总体:

使用方面除了官网的wiki外,推荐阅读

作者:夜尽天明_
链接:https://juejin.cn/post/7048917724126248967
来源:稀土掘金

  • 非annotation 方式,执行不是jdk proxy模式
  • annotation 方式,和rulebook 类似使用jdk
    proxy模式,但由于本质居于pojo和继承模式,proxy调用比较简单,采用return class类指定方法
  • 每个rule 只有一个action方法,这点与rulebook不同
  • 支持CompositeRule,默认有3种,但不支持rulebook chain式按order执行
  • 两种执行引擎,DefaultRulesEngine 只执行一次,InferenceRulesEngine 会循环执行,直到所有rule的evaluation 返回false
  • evaluation 相当于rulebook的condition,action相当于rulebook 的then

核心类及代码

public final class DefaultRulesEngine extends AbstractRulesEngine 的执行函数

void doFire(Rules rules, Facts facts) {if (rules.isEmpty()) {LOGGER.warn("No rules registered! Nothing to apply");return;}logEngineParameters();log(rules);log(facts);LOGGER.debug("Rules evaluation started");for (Rule rule : rules) {final String name = rule.getName();final int priority = rule.getPriority();if (priority > parameters.getPriorityThreshold()) {LOGGER.debug("Rule priority threshold ({}) exceeded at rule '{}' with priority={}, next rules will be skipped",parameters.getPriorityThreshold(), name, priority);break;}//执行listener ,如果有返回false ,那么就不执行当前ruleif (!shouldBeEvaluated(rule, facts)) {LOGGER.debug("Rule '{}' has been skipped before being evaluated", name);continue;}boolean evaluationResult = false;try {evaluationResult = rule.evaluate(facts);} catch (RuntimeException exception) {LOGGER.error("Rule '" + name + "' evaluated with error", exception);triggerListenersOnEvaluationError(rule, facts, exception);// give the option to either skip next rules on evaluation error or continue by considering the evaluation error as falseif (parameters.isSkipOnFirstNonTriggeredRule()) {LOGGER.debug("Next rules will be skipped since parameter skipOnFirstNonTriggeredRule is set");break;}}if (evaluationResult) {LOGGER.debug("Rule '{}' triggered", name);triggerListenersAfterEvaluate(rule, facts, true);try {triggerListenersBeforeExecute(rule, facts);rule.execute(facts);LOGGER.debug("Rule '{}' performed successfully", name);triggerListenersOnSuccess(rule, facts);if (parameters.isSkipOnFirstAppliedRule()) {LOGGER.debug("Next rules will be skipped since parameter skipOnFirstAppliedRule is set");break;}} catch (Exception exception) {LOGGER.error("Rule '" + name + "' performed with error", exception);triggerListenersOnFailure(rule, exception, facts);if (parameters.isSkipOnFirstFailedRule()) {LOGGER.debug("Next rules will be skipped since parameter skipOnFirstFailedRule is set");break;}}} else {LOGGER.debug("Rule '{}' has been evaluated to false, it has not been executed", name);triggerListenersAfterEvaluate(rule, facts, false);if (parameters.isSkipOnFirstNonTriggeredRule()) {LOGGER.debug("Next rules will be skipped since parameter skipOnFirstNonTriggeredRule is set");break;}}}
}private boolean shouldBeEvaluated(Rule rule, Facts facts) {return triggerListenersBeforeEvaluate(rule, facts);
}
private boolean triggerListenersBeforeEvaluate(Rule rule, Facts facts) {return ruleListeners.stream().allMatch(ruleListener -> ruleListener.beforeEvaluate(rule, facts));
}

public final class InferenceRulesEngine extends AbstractRulesEngine 循环执行,指定facts结果满足了所有condition都不符合,才停止执行相关rules的核心代码如下:

@Override
public void fire(Rules rules, Facts facts) {Set<Rule> selectedRules;//默认只要有selectCandidates(rules, facts) 就会执行,如果facts 没有变化那么selectCandidates返回rules就会一直一样,即不断循环执行do {LOGGER.debug("Selecting candidate rules based on the following facts: {}", facts);selectedRules = selectCandidates(rules, facts);if (!selectedRules.isEmpty()) {delegate.fire(new Rules(selectedRules), facts);} else {LOGGER.debug("No candidate rules found for facts: {}", facts);}} while (!selectedRules.isEmpty());
}private Set<Rule> selectCandidates(Rules rules, Facts facts) {Set<Rule> candidates = new TreeSet<>();//如果facts 没有变化for (Rule rule : rules) {if (rule.evaluate(facts)) {candidates.add(rule);}}return candidates;
}

使用InferenceRulesEngine 一定要修改fact。

UnitRuleGroup 所有rule作为一个整体判断是否执行

@Override
public boolean evaluate(Facts facts) {if (!rules.isEmpty()) {for (Rule rule : rules) {if (!rule.evaluate(facts)) {return false;}}return true;}return false;
}

public class ActivationRuleGroup extends CompositeRule
通过selectedRule来(随机)选择了第一个condition符合的rule

@Override
public boolean evaluate(Facts facts) {for (Rule rule : rules) {if (rule.evaluate(facts)) {selectedRule = rule;return true;}}return false;
}

public class ConditionalRuleGroup extends CompositeRule 首先判断RuleWithHighestPriority的condition是否满足,如果满足再选择重所有condition符合的rule进行fire

@Override
public boolean evaluate(Facts facts) {successfulEvaluations = new HashSet<>();conditionalRule = getRuleWithHighestPriority();if (conditionalRule.evaluate(facts)) {for (Rule rule : rules) {if (rule != conditionalRule && rule.evaluate(facts)) {successfulEvaluations.add(rule);}}return true;}return false;
}private Rule getRuleWithHighestPriority() {List<Rule> copy = sort(rules);// make sure we only have one rule with the highest priorityRule highest = copy.get(0);if (copy.size() > 1 && copy.get(1).getPriority() == highest.getPriority()) {throw new IllegalArgumentException("Only one rule can have highest priority");}return highest;
}

RuleGroup支持从yml自动创建,或者手工创建,yml自动创建代码

switch (ruleDefinition.getCompositeRuleType()) {case "UnitRuleGroup":compositeRule = new UnitRuleGroup(name);break;case "ActivationRuleGroup":compositeRule = new ActivationRuleGroup(name);break;case "ConditionalRuleGroup":compositeRule = new ConditionalRuleGroup(name);break;default:throw new IllegalArgumentException("Invalid composite rule type, must be one of " + ALLOWED_COMPOSITE_RULE_TYPES);
}

代码创建

public void setUp() {
conditionalRule = new TestRule("conditionalRule", "description0", 0, true);
rule1 = new TestRule("rule1", "description1", 1, true);
rule2 = new TestRule("rule2", "description2", 2, true);
conditionalRuleGroup = new ConditionalRuleGroup();
conditionalRuleGroup.addRule(rule1);
conditionalRuleGroup.addRule(rule2);
conditionalRuleGroup.addRule(conditionalRule);
rules.register(conditionalRuleGroup);
}

从yml文件创建都基于AbstractRuleFactory类

在这里插入图片描述

扩展

可以根据需要去扩展AbstractRuleFactory和CompositeRule,依托priority属性实现类似rulebook 的chain 执行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/21633.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

家政小程序开发-H5+小程序

移动互联网的发展&#xff0c;微信小程序逐渐成为商家拓展线上业务的重要手段。家政服务作为日常生活中不可或缺的一部分&#xff0c;也开始尝试通过小程序来提高服务质量和效率。 下面是一篇关于家政小程序开发的H5小程序的文章&#xff0c;希望对您有所帮助。 家政服…

java并发编程 10:AQS

目录 什么是AQS原理 什么是AQS juc包的结构如下图&#xff1a; AQS就是AbstractQueuedSynchronizer&#xff0c;是个抽象类&#xff0c;实现了自己的一些方法。它是阻塞式锁和相关的同步器工具的框架。很多并发类都是基于它实现的&#xff0c;如&#xff1a;ReentrantLock、Co…

【计算机视觉】简述对EQ-Net的理解

最近又看了一些点云分割的文章&#xff0c;近两年点云分割的文章是真的少&#xff0c;不知道是不是点云分割算法接近了末端。这篇文章主要提出了一个基于查询方法的统一范式&#xff0c;它解决了一些不仅仅是点云分割的问题&#xff0c;还解决了三维点云分类和三维目标检测的问…

牧云·云原生安全平台v2.0.0正式上线,云上想不安全都难!

**前言&#xff1a;**牧云云原生安全平台是长亭牧云团队以开源社区为生态载体技术积累为驱动所打造的云原生安全平台。首创双模探针架构&#xff0c;可选用 Agentless/Agent 多种方案进行部署&#xff0c;覆盖制品、运行时、集群全流程安全&#xff0c;开箱即用、快速实施、成本…

设计模式——观察者模式

观察者模式&#xff08;世界线的观测者&#xff09; 定义 观察者模式&#xff08;Observer Partern&#xff09;也叫做发布/订阅模式&#xff08;Publish/Subscribe&#xff09;&#xff0c;一种以监听为核心的设计模式。 定义对象间一种一对多的依赖关系&#xff0c;使得每…

UG\NX二次开发 获取对象的边界包容盒 UF_MODL_ask_bounding_box

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 简介: 获取对象的边界包容盒 UF_MODL_ask_bounding_box,只能得到绝对坐标系下的边界包容盒,速度快,结果不精确。 效果: 代码: //UF_MODL_ask_bounding_box #include "me.hpp" #include &…

vscode 端口转发实现端口映射,实现端口自由

用vscode连接server进行开发&#xff0c; 是非常方便的&#xff0c;但很多时候&#xff0c;server的端口开放的很有限&#xff0c;那么就可以利用vscode进行端口映射 举一个应用场景&#xff1a; 先通过A利用vscode 连接B&#xff0c;然后再vscode 的port窗口进行端口转发&…

美工面试题目(合集)

美工面试题目篇1 1、目前常用的WEB标准静态页面语言是。(4分) 2、改变元素的外边距用&#xff0c;改变元素的内填充用。(6分) 3、在Table中&#xff0c;TR是&#xff0c;TD是。(6分) 4、如果给一行两列的表格(table)定义高度样式&#xff0c;在标签中定义最合理&#xff0c…

springboot人事管理系统

本项目在开发和设计过程中涉及到原理和技术有: B/S、java技术和MySQL数据库等等&#xff1b;将按以下章节进行开发设计&#xff1b; 绪论&#xff1b;剖析项目背景,说明研究的内容。 开发技术&#xff1b;系统主要使用了java技术&#xff0c;b/s模式和myspl数据库&#xff0c;并…

从C语言到C++_26(set+map+multiset+multimap)力扣692+349+牛客_单词识别

目录 1. 关联式容器 1.1 树形结构的关联式容器 2. set的相关介绍 2.1 set的构造和迭代器 2.2 set的容量和操作函数 2.3 set使用代码 2.4 multiset使用 3. map的相关介绍 3.1 键值对 3.2 map的构造和迭代器 3.3 map的容量和操作函数 3.4 map使用代码 3.5 multimap使…

python脚本(Word转PDF格式小工具)

from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QMessageBox from PyQt5.QtCore import Qt import sys import os from comtypes import client#文件转换脚本 class FileDropWidget(QWidget):def __init__(self):super().__init__()self.initUI()de…

应用于智能眼镜上实现检测功能的距离传感芯片

随着智能穿戴设备的发展&#xff0c;各种新型的电子产品不断被研发出来&#xff0c;诸如智能头盔、智能手表、智能手环等等&#xff0c;智能眼镜就是其中一种&#xff0c;国内华为、小米相继推出智能产品。 智能眼镜具有和智能耳机相似的功能&#xff0c;不仅保留眼镜本身功能…