1、背景
此处介绍一下 drools 中 then 部分的写法,以及一些内置的方法,比如 insert/delete/modify 等等。同时也介绍一下 rule 的继承,和在 when 中实现 if else if 等操作。
2、支持的方法
drools提供了一些内置的方法,这些方法会修改drools的 工作内存 中 Fact 对象的值。从而会导致重新进行模式匹配。
2.1 insert 插入对象到工作内存中
insert 是向工作内存中插入对象,同时会导致重新进行规则的模式匹配。同时当规则不满足时,不会自动删除。
2.1.1 需求
当发生火灾 Fire 时,向工作内存中插入一个 Alarm 对象,告警发生后,删除工作内存中的 Fire 对象,然后检测 Alarm 对象是否还存在。
2.1.2 drl文件编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package rules import com.huan.drools.insertmethod.Fire import com.huan.drools.insertmethod.Alarm rule "insert_发生火灾时,往工作内存中插入告警对象" when $fire: Fire() then System.out.println( "1、发生火灾时,往工作内存中插入告警对象" ); insert( new Alarm($fire)); end rule "insert_当规则内存中存在告警对象,进行告警,然后删除火灾对象" when $fire: Fire() $alarm: Alarm( fire == $fire ) then System.out.println( "2、进行告警,然后删除对应的火灾对象" ); end rule "insert_检测告警对象是否还是存在-01" when Alarm() then System.out.println( "3、insert 插入的告警对象还存在" ); // 删除工作内存中的Fire对象 delete($fire); end rule "insert_检测告警对象不存在" when not Alarm() then System.out.println( "3、insert 插入的告警对象不存在" ); end |
此处使用的是 insert 进行插入
2.1.3 部分java代码编写
1 2 3 4 |
// 将火灾对象插入到工作内存中 kieSession.insert( new Fire()); // 只触发规则名称以 insert_ 开头的规则 kieSession.fireAllRules( new RuleNameStartsWithAgendaFilter( "insert_" )); |
2.1.4 运行结果
1、发生火灾时,往工作内存中插入告警对象
2、进行告警,然后删除对应的火灾对象
3、insert 插入的告警对象还存在
2.1.5 结论 insert可以向工作内存中插入Fact对象。 insert方法调用后,会导致模式的重新匹配,导致之前不会执行的规则,重新执行。 insert方法插入到工作内存的对象,在规则不成立时,不会自动删除,需要手动删除,注意和insertLogical的区别
2.2 insertLogical 插入对象到工作内存中
insert 是向工作内存中插入对象,同时会导致重新进行规则的模式匹配。同时当规则不满足时,会自动删除。
2.2.1 需求
当发生火灾 Fire 时,向工作内存中插入一个 Alarm 对象,告警发生后,删除工作内存中的 Fire 对象,然后检测 Alarm 对象是否还存在。
2.2.2 drl文件编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package rules import com.huan.drools.Fire import com.huan.drools.Alarm rule "insertLogical_发生火灾时,往工作内存中插入告警对象" when $fire: Fire() then System.out.println( "1、发生火灾时,往工作内存中插入告警对象" ); insertLogical( new Alarm($fire)); end rule "insertLogical_当规则内存中存在告警对象,进行告警,然后删除火灾对象" when $fire: Fire() $alarm: Alarm( fire == $fire ) then System.out.println( "2、进行告警,然后删除对应的火灾对象" ); delete($fire); end rule "insertLogical_检测告警对象是否还是存在-01" when Alarm() then System.out.println( "3、insertLogical 插入的告警对象还存在" ); end rule "insertLogical_检测告警对象不存在" when not Alarm() then System.out.println( "3、insertLogical 插入的告警对象不存在" ); end |
此处使用的是 insertLogical 插入
2.2.3 部分java代码编写
1 2 |
kieSession.insert(new Fire()); kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("insertLogical_")); |
2.2.4 运行结果
1、发生火灾时,往工作内存中插入告警对象
2、进行告警,然后删除对应的火灾对象
3、insertLogical 插入的告警对象不存在
2.2.5 结论 insertLogical可以向工作内存中插入Fact对象。 insertLogical方法调用后,会导致模式的重新匹配,导致之前不会执行的规则,重新执行。 insertLogical方法插入到工作内存的对象,在规则不成立时,会自动删除注意和insert的区别
2.3、update 更新工作内存中的对象
update: 使用它来指定要更新的字段和整个相关Fact,并将更改通知 Drools 引擎。 Fact发生更改后,您必须在更改可能受更新值影响的另一个事实之前调用 update。 为避免此添加步骤,请改用 modify 方法。
2.3.1 需求
规则一: 当工作内存中存在火灾对象 Fire ,并且名字name为空时触发规则,同时在设置火灾的名字为 大火灾 。
规则二: 当火灾存在名字时,输出火灾名字
2.3.2 drl 文件编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package rules import com.huan.drools.Fire import com.huan.drools.Alarm rule "update_当存在火灾对象时,设置一个火灾的名字" when $fire: Fire(name == null ) then System.out.println( "1、设置火灾名字" ); $fire.setName( "大火灾" ); update($fire) end rule "update_当火灾对象存在名字时触发" when $fire: Fire(name != null ) then System.out.println( "2、火灾对象的名字为: " + $fire.getName()); end |
2.3.3 部分java文件编写
1 2 |
kieSession.insert( new Fire()); kieSession.fireAllRules( new RuleNameStartsWithAgendaFilter( "update_" )); |
2.3.4 运行结果
1、设置火灾名字
2、火灾对象的名字为: 大火灾
2.3.4 结论 update 会导致模式的重新匹配。 update 会修改工作对象内存中的值。
2.4、modify 更新工作内存中的对象
modify: 使用它来指定要为Fact对象修改的字段并将更改通知 Drools 引擎。 此方法提供了一种结构化的事实更新方法。 它将更新操作与 setter 调用相结合以更改对象字段。
2.4.1 需求
规则一: 当工作内存中存在火灾对象 Fire ,并且名字name为空时触发规则,同时在设置火灾的名字为 大火灾 。
规则二: 当火灾存在名字时,输出火灾名字
2.4.2 drl 文件编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package rules import com.huan.drools.Fire import com.huan.drools.Alarm rule "modify_当存在火灾对象时,设置一个火灾的名字" when $fire: Fire(name == null ) then System.out.println( "1、设置火灾名字" ); modify($fire){ setName( "大火灾" ) } end rule "modify_当火灾对象存在名字时触发" when $fire: Fire(name != null ) then System.out.println( "2、火灾对象的名字为: " + $fire.getName()); end |
2.4.3 部分java文件编写
1 2 |
kieSession.insert( new Fire()); kieSession.fireAllRules( new RuleNameStartsWithAgendaFilter( "modify_" )); |
2.4.4 运行结果 1、设置火灾名字 2、火灾对象的名字为: 大火灾
2.4.5 结论 modify 会导致模式的重新匹配。 modify 会修改工作对象内存中的值。一般情况下使用 modify ,不要使用 update 。
2.5 delete 删除工作内存中的对象
用法: delete(<object>)
retract 也是和 delete 一样的效果,但是推荐使用 delete 。
3、drools变量的简单使用
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package rules rule "drools_变量的使用" wh eval( true ) then System.out.println( "Match激活的当前触发规则: " + drools.getMatch()); System.out.println( "当前触发规则的名字: " + drools.getRule().getName()); // System.out.println("终止规则执行fireUntilHalt(): " + drools.getKieRuntime().halt()); // System.out.println("激活AgendaGroup组: " + drools.getKieRuntime().getAgenda().getAgendaGroup( "CleanUp" ).setFocus()); System.out.println( "获取所有全局变量: " + drools.getKieRuntime().getGlobals()); // System.out.println("设置全局变量:" + drools.getKieRuntime().setGlobal("username","huan"); ); // System.out.println("获取查询结果:" + drools.getKieRuntime().getQueryResults()); end |
4、规则的继承
4.1 需求
规则一: 如果用户( customer )的年龄( age )大于60岁,则打 0.9 折。
规则二: 在规则一的基础上,如果用户有车( car ),则可以免费停车( freeParking )。
4.2 drl文件编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package rules import com.huan.drools.Customer import com.huan.drools.Car rule "rule_extends_规则一" when $c: Customer(age > 60 ) then modify($c){ setDiscount( 0.9 ) } System.out.println( "触发规则一:用户年龄>60岁,打0.9折" ); end // 规则二继承规则一的条件 rule "rule_extends_规则二" extends "rule_extends_规则一" when $car: Car() then modify($car){ setFreeParking( true ) } System.out.println( "触发规则二:用户有车,免费停车" ); end |
此处 rule_extends_规则二 继承了 rule_extends_规则一 ,所以规则一的条件也继承了。
4.3 部分java代码
1 2 3 4 5 6 |
Car car = new Car(); Customer customer = new Customer(); customer.setAge( 65 ); kieSession.insert(customer); kieSession.insert(car); kieSession.fireAllRules( new RuleNameStartsWithAgendaFilter( "rule_extends_" )); |
客户有车,并且年龄是65岁,满足上方的规则一和规则二
4.4 运行结果
触发规则一:用户年龄>60岁,打0.9折
触发规则二:用户有车,免费停车
4.5 结论
可以看到在 rule 上使用 extends 关键字,可以实现规则的继承。
5、使用do[...]语法重写上方继承的例子
5.1 需求
只要用户大于60岁,直接打0.9折,如果还有车,则可以免费停车。
5.2 drl文件编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package rules import com.huan.drools.Customer import com.huan.drools.Car rule "命名结果_rule" when $c: Customer(age > 60 ) do [giveDiscount] // 当上方的条件成立时执行 then [giveDiscount] $car: Car() // 此条件成立时,执行默认的 then then modify($car){ setFreeParking( true ) }; System.out.println( "用户有车,免费停车" ); then [giveDiscount] modify($c){ setDiscount( 0.9 ) }; System.out.println( "用户年龄>60岁,打0.9折" ); end |
解释: 见上方的规则文件里的注视
5.3 部分java代码编写
1 2 3 4 5 6 |
Car car = new Car(); Customer customer = new Customer(); customer.setAge( 65 ); kieSession.insert(customer); kieSession.insert(car); kieSession.fireAllRules( new RuleNameStartsWithAgendaFilter( "命名结果_" )); |
5.4 运行结果
用户年龄>60岁,打0.9折
用户有车,免费停车
也实现了需求
5.5 结论
通过 when 中使用 do[名字] 然后 then then 名字 也可以实现。
6、实现 if else if 的效果
6.1 需求
完成类似 if else if else 效果。 见下方的各种执行结果 。
6.2 规则文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
rule "if else-if" when $customer: Customer(age > 60 ) // 规则内存中存在Customer对象,并且age>60 if ($customer.getLevel() == 1 ) do [level1] // 用户的级别是1,执行then[level1],然后继续执行下方的条件 else if ($customer.getLevel() == 2 ) break [level2] // 用户的级别是2,执行then[level2],不在执行下方的条件 else do [levelOther] // 其他的level级别,执行then[levelOther],然后在执行下方的条件 Car() then System.out.println( "我执行了" ); then[level1] System.out.println( "level1" ); then[level2] System.out.println( "level2" ); then[levelOther] System.out.println( "levelOther" ); end |
6.3 执行结果图
6.4 各种执行结果-也就是上图的解释
1、 Customer 的 age 小于 60 。
输出: 没有输出。
2、 Customer 的 age 大于 60 并且 level=1 ,没有 Car 。
输出: level1
3、 Customer 的 age 大于 60 并且 level=1 ,有 Car 。
输出: level1 我执行了
4、 Customer 的 age 大于 60 并且 level=2 ,没有 Car 。
输出: level2
5、 Customer 的 age 大于 60 并且 level=2 ,有 Car 。
输出: level2
6、 Customer 的 age 大于 60 并且 level=3 ,没有 Car 。
输出: levelOther
7、 Customer 的 age 大于 60 并且 level=3 ,有 Car 。
输出: levelOther 我执行了
6.5 do和 break 有什么区别
do :执行完之后,还会继续判断后面的执行条件。 ( 即还会执行后面的Car判断,根据是否有Car获取不同的结果 )
break :执行完之后,不会在判断后面的执行条件。( 即忽略了后面的Car判断,rule执行完了 )
7.完整代码
https://gitee测试数据/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-then
8.参考文档
https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-rules-THEN-con_drl-rules
到此这篇关于drools中then部分的写法的文章就介绍到这了,更多相关drools中then写法内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://blog.csdn.net/QIWEIscrm/article/details/124961695
查看更多关于drools中then部分的写法(推荐)的详细内容...