easy-rule 学习
Easyrule是个规则引擎,类似于drools,我们来熟悉一下这个东西
[ ] 一个简单实例规则,这个规则会被一直触发,然后行为是打印helloWorld
@Rule(name="helloWorld",description = "总是打印helloWorld")
public class HelloWorldRule {
@Condition
public boolean when(){
return true;
} @Action
public void then(){
System.out.println("hello world");
}
}public class DemoLauncher {
public static void main(String[] args) {
Facts facts=new Facts();
//规则集合定义并注册
Rules rules=new Rules();
rules.register(new HelloWorldRule()); //创建一个规则引擎,并驱动rules
RulesEngine rulesEngine=new DefaultRulesEngine();
//执行
rulesEngine.fire(rules,facts);
}
}日志打印:
hello world
配上日志包,观察下框架的日志
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'helloWorld', description = '总是打印helloWorld', priority = '2147483646'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'helloWorld' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'helloWorld' performed successfully
hello world
org.slf4j.simpleLogger.defaultLogLevel=debug
[ ] FizzBuzz : 数字从一到100 当能被5整除的时候发出fizz,被7整除时候发出buzz,同时被5和7整除就发出fizzbuzz
java简单实现:循环然后用ifelse判断该怎么处理
public class JavaDeme {
public static void main(String[] args) {
for(int i=0;i<100;i++){
if(i%5==0&&i%7==0){
System.out.println("fizzbuzz"+":"+i);
}else if(i%5==0){
System.out.println("fizz:"+i);
}else if(i%7==0){
System.out.println("buzz:"+i);
}else{
//System.out.println("啥也不是"+i);
}
// System.out.println();
}
}
}
easyrule实现先为每个规则写个rule
FizzRule
@Rule
public class FizzRule { @Condition
public boolean isFizz(@Fact("number") Integer number) {
return number % 5 == 0;
} @Action
public void printFizz() {
System.out.print("fizz");
}
// 优先级为1
@Priority
public int getPriority() {
return 1;
}
}
BuzzRule
@Rule
public classBuzzRule { @Condition
public booleanisBuzz(@Fact("number") Integer number) {
returnnumber % 7 == 0;
} @Action
public voidprintBuzz() {
System.out.print("buzz");
}
//优先级2
@Priority
public intgetPriority() {
return2;
}
}
FizzBuzzRule :BuzzRule,和FizzRule 整合的规则
public class FizzBuzzRule extends UnitRuleGroup {
public FizzBuzzRule(Object... rules){
for(Object rule:rules){
addRule(rule);
}
} @Override
public int getPriority(){
return 0;
}
}
两个规则都不符合
@Rule
public class NonFizzBuzzRule {
@Condition
public boolean isNotFizzNorBuzz(@Fact("number") Integer number){
// can return true, because this is the latest rule to trigger according to assigned priorities
// and in which case, the number is not fizz nor buzz
return number % 5 != 0 || number % 7 != 0;
}
@Action
public void printInput(@Fact("number") Integer number) {
System.out.print(number);
} @Priority
public int getPriority() {
return 3;
}
}
主方法入口:
public class FizzBuzzWithEasyRules {
public static void main(String[] args) {
RulesEngineParameters parameters=new RulesEngineParameters();
// 满足第一个规则就退出
parameters.setSkipOnFirstAppliedRule(true); // 引擎
RulesEngine rulesEngine=new DefaultRulesEngine();
//RulesEngine rulesEngine=new DefaultRulesEngine(parameters); // 规则
Rules rules=new Rules();
rules.register(new FizzRule());
rules.register(new BuzzRule());
rules.register(new FizzBuzzRule(new FizzRule(),new BuzzRule()));
rules.register(new NonFizzBuzzRule()); //匹配规则
Facts facts=new Facts();
for(int i=0;i<100;i++){
facts.put("number",i);
rulesEngine.fire(rules,facts);
System.out.println();
} }
}
日志
31
32
33
34
fizzbuzzfizzbuzz // 这里打印了两边,因为引擎参数没有把跳出判断加上
36
37
38
39
fizz40
31
32
33
34
fizzbuzz
36
37
38
[ ] shop:这个示例展示MVEL表达式在EasyRules中的应用,这里示例我们实现一个功能: 小商店卖酒,不能卖给未成年人(法定年龄小于18岁的人)
- 定义一个人的对象
@Data
public class Person {
private String name; private int age; private boolean adult; }
MVEL 表达式来写一个规则,这个规则做两件事,首先判断人是不是18岁以上,如果是我们将人的adult属性修改为true,成年人。买酒的行为判断人是否成年如果未成年则拒绝。
Rule ageRule=new MVELRule()
.name("年龄规则")
.description("检查用户年龄是否大于18岁")
.priority(1)
.when("person.age > 18")
.then("person.setAdult(true);");
另外一个规则,是否可以买酒,这次用一个另外的方式来配置规则,写yml文件的方式代码如下:
name: "alcohol rule"
description: "小孩子不能喝酒"
priority: 2
condition: "person.isAdult()==false"
# 这里是actions数组类型-容易写成action
actions:
- "System.out.println(\\"Shop: Sorry, you are not allowed to buy alcohol\\");"
运行:用MVELRuleFactory加载规则
public class MvelRuleDemo {
public static void main(String[] args) throws Exception {
Rule ageRule=new MVELRule()
.name("年龄规则")
.description("检查用户年龄是否大于18岁")
.priority(1)
.when("person.age > 18")
.then("person.setAdult(true);");
//定义工厂类
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
URL url = MvelRuleDemo.class.getClassLoader().getResource("rule/alcohol-rule.yml");
Rule alcoholRule = ruleFactory.createRule(new FileReader(url.getPath())); // 规则合集
Rules rules=new Rules();
rules.register(ageRule);
rules.register(alcoholRule); //规则引擎
RulesEngine rulesEngine=new DefaultRulesEngine();
// 实例
System.out.println("来判断接下来的客人能不能买酒");
Person p=new Person();
p.setAge(17);
p.setName("小李"); Facts facts=new Facts();
facts.put("person",p); // 执行
rulesEngine.fire(rules,facts);
}
}
来判断接下来的客人能不能买酒
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = '年龄规则', description = '检查用户年龄是否大于18岁', priority = '1'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'alcohol rule', description = '小孩子不能喝酒', priority = '2'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact { person : Person(name=小李, age=17, adult=false) }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '年龄规则' has been evaluated to false, it has not been executed
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'alcohol rule' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'alcohol rule' performed successfully
Shop: Sorry, you are not allowed to buy alcohol
修改为19岁后执行-执行完打印一下用户信息,发现用户的成年状态被修改了
来判断接下来的客人能不能买酒
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = '年龄规则', description = '检查用户年龄是否大于18岁', priority = '1'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'alcohol rule', description = '小孩子不能喝酒', priority = '2'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact { person : Person(name=小李, age=19, adult=false) }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '年龄规则' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '年龄规则' performed successfully
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'alcohol rule' has been evaluated to false, it has not been executed
Person(name=小李, age=19, adult=true)
[ ] InferenceRulesEngine 持续对已知事实应用规则,直到不再应用规则为止,上面的例子们引擎由默认改为这个的话,代码停不下来,可以试一下,源码也可以读一下处理方式由很大不同。
default
@Override
public void fire(Rules rules, Facts facts) {
triggerListenersBeforeRules(rules, facts);
doFire(rules, facts);
triggerListenersAfterRules(rules, facts);
} 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;
}
if (!shouldBeEvaluated(rule, facts)) {
LOGGER.debug("Rule '{}' has been skipped before being evaluated",
name);
continue;
}
if (rule.evaluate(facts)) {
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;
}
}
}
}
inferenceRulesEngine: 只是在默认的执行外包装了以下一下代码
@Override
public void fire(Rules rules, Facts facts) {
Set<Rule> selectedRules;
do {
LOGGER.debug("Selecting candidate rules based on the following facts: {}", facts);
selectedRules = selectCandidates(rules, facts);
if(!selectedRules.isEmpty()) {
// 这个delegate就是上面默认的规则引擎
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<>();
for (Rule rule : rules) {
if (rule.evaluate(facts)) {
candidates.add(rule);
}
}
return candidates;
}
示例展示一个空调系统,当温度过高时不断降温操作直至温度降低到合适的度数,
创建一个条件类,来决定什么时候是热
public class HighTemperatureConditon implements org.jeasy.rules.api.Condition {
// 中文意思评估评定-
@Override
public boolean evaluate(Facts facts) {
Integer temperature=facts.get("temperature"); return temperature>25;
} static HighTemperatureConditon itIsHot(){
return new HighTemperatureConditon();
}
}
action类,满足条件后的执行内容
public class DecreaseTemperactureAction implements org.jeasy.rules.api.Action {
@Override
public void execute(Facts facts) throws Exception {
System.out.println("温度过高-降温");
Integer temperature=facts.get("temperature");
facts.put("temperature",temperature-1);
}
static DecreaseTemperactureAction decreaseTemperacture(){
return new DecreaseTemperactureAction();
}
}
执行类-我们注册规则指定规则的触发条件为温度过高,rule.evaluate 方法,然后then执行的结果是:action.execute
public class AirLauncherDemo {
public static void main(String[] args) {
Facts facts=new Facts();
facts.put("temperature",30); // 规则
Rule airRule= new RuleBuilder()
.name("空调测试")
.when(HighTemperatureConditon.itIsHot())
.then(DecreaseTemperactureAction.decreaseTemperacture())
.build(); Rules rules=new Rules();
rules.register(airRule); //inference引擎,持续不断的执行
RulesEngine rulesEngine=new InferenceRulesEngine(); rulesEngine.fire(rules,facts);
System.out.println(facts.get("temperature").toString());
}
}
日志-我们发现一直降温到25度
[main] DEBUG org.jeasy.rules.core.InferenceRulesEngine - Selecting candidate rules based on the following facts: [ { temperature : 30 } ]
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = '空调测试', description = 'description', priority = '2147483646'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact { temperature : 30 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' performed successfully
[main] DEBUG org.jeasy.rules.core.InferenceRulesEngine - Selecting candidate rules based on the following facts: [ { temperature : 29 } ]
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = '空调测试', description = 'description', priority = '2147483646'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact { temperature : 29 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' performed successfully
[main] DEBUG org.jeasy.rules.core.InferenceRulesEngine - Selecting candidate rules based on the following facts: [ { temperature : 28 } ]
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = '空调测试', description = 'description', priority = '2147483646'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact { temperature : 28 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' performed successfully
[main] DEBUG org.jeasy.rules.core.InferenceRulesEngine - Selecting candidate rules based on the following facts: [ { temperature : 27 } ]
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = '空调测试', description = 'description', priority = '2147483646'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact { temperature : 27 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' performed successfully
[main] DEBUG org.jeasy.rules.core.InferenceRulesEngine - Selecting candidate rules based on the following facts: [ { temperature : 26 } ]
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = '空调测试', description = 'description', priority = '2147483646'}
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact { temperature : 26 }
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' triggered
[main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule '空调测试' performed successfully
[main] DEBUG org.jeasy.rules.core.InferenceRulesEngine - Selecting candidate rules based on the following facts: [ { temperature : 25 } ]
[main] DEBUG org.jeasy.rules.core.InferenceRulesEngine - No candidate rules found for facts: [ { temperature : 25 } ]
温度过高-降温
温度过高-降温
温度过高-降温
温度过高-降温
温度过高-降温
25
这个示例说明,InferenceRulesEngine 会不断的重新进行判断执行,所以必须在满足条件执行的操作中修改自身实例。不然会崩溃
easy-rule 学习的更多相关文章
- jquery easy ui 学习 (6) basic validatebox
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (9)Pagination in TreeGrid 分页
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (8)basic treegrid
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (7) TreeGrid Actions
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (5) windowlayout
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (4) window 打开之后 限制操纵后面元素属性
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (3) window 限制在父类窗体内
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (2) customtools window
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jquery easy ui 学习 (1)Basic Window
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- easy ui 学习笔记,不断整理中............
$.message.show({//浏览器右下角弹框,我列出了几个属性,具体请看API title: '提示', msg: '恭 ...
随机推荐
- Java File常见用法
一.构造方法 File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例. File(String pathname) 通过将给定的路径名字符 ...
- 四:HttpServletRequest对象
一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象 ...
- 使用HttpURLConnection多线程下载
1 import java.io.IOException; 2 import java.io.InputStream; 3 import java.io.RandomAccessFile; 4 imp ...
- 多线程编程<五>
1 /** 2 * 中断线程:当线程由于调用sleep(),join(),wait()而暂停时,如果中断它,则会收到一个InterruptedException异常. 3 * 调用Thread.isI ...
- HCNP Routing&Switching之OSPF LSA类型
前文我们了解了OSPF中的虚连接相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15202348.html:今天我们来聊一聊OSPF数据包中LSA类型相 ...
- 检测一个页面所用的时间的js
window.onload = function () { var loadTime = window.performance.timing.domContentLoadedEventEnd-wind ...
- uni-app 小程序从零开始的开发流程
前言 本文基于 HBuilderX 3.1.22 + 微信开发者工具 1.05.2106300为主要内容进行说明. 文档版本:1.0.0 更新时间:2021-09-03 15:32 一.准备 uni- ...
- PyCharm——滚动鼠标调整字体大小
- Flask(2)- 第一个 Flask Application
安装 flask Flask 是一个 Web 框架,使用它首先需要安装 pip3 install flask 导入 Flask 模块 import flask 最简单的一个栗子 主代码 from fl ...
- JDK 1.7 正式发布,Oracle 官宣免费提供!“新版任你发,我用JDK 8”或成历史?
Oracle公司JDK 17正式发布,JDK 17属于长期支持(LTS)版本,也就是获得8年的技术支持,自2021年9月至2029年9月截止. JDK 17版本更新了很多比较实用的新特性,关于此版本的 ...