如何解决在 lhs 和 rhs 中流口水不同的变量值
我有两个规则
rule "test1"
when
$cr: MyContext(flag1 == 1)
then
System.out.println("<---- Test1 start ---->");
$cr.setFlag1(10);
System.out.println("<---- Test1 end ---->");
end
rule "test2" salience -1
when
$cr: MyContext($flag1: flag1 == 1)
then
System.out.println("<---- Test2 start ---->");
System.out.println($flag1);
System.out.println("<---- Test2 end ---->");
end
I rule1,我正在检查变量 MyContext.flag1 是否为 1。既然是这样,我将其更改为 10。 我 rule2,我正在检查变量 MyContext.flag1 是否为 1。 我没想到这条规则会在 flag1 为 10 时执行。
但令人惊讶的是,它执行并打印 flag1 为 10。
它如何在 rule2 的 LHS 中将 flag1 == 1 评估为真,而在 RHS 中将 flag1 打印为 10?
解决方法
最初,Drools 评估必须根据您工作记忆中的事实来触发两个规则。因此,要解雇的规则的议程是(根据您的显着性):
- 等待触发的规则“test1”......
- 等待触发的规则“test2”......
你错过的是,如果你不这么说 Drools,议程就不会被修改。 在您的情况下,规则“test1”被触发,然后从议程中删除,议程的新状态是:
- 等待触发的规则“test2”......
那么接下来会发生什么,规则“test2”被触发,因为你改变了你的事实,drools 打印它的新值,即 10。所以行为是好的。
您需要的是在规则“test1”中修改后调用 update($cr),这意味着:根据我的事实 $cr 使用所有规则更新议程。 结果是 Drools 现在将从其议程中删除规则“test2”。
,当您触发 drools 规则时,框架会在工作内存中获取您的规则输入并确定哪些规则匹配。然后对这些规则匹配进行排序(按显着性或自然顺序),然后按顺序触发。
因此,当您触发规则时,“test1”和“test2”被确定为匹配项。然后 Drools 继续首先触发“test1”,然后是“test2”。
如果你想让 Drools 重新评估规则匹配,你需要“告诉”框架你已经对工作内存进行了更改。为此,您有以下内置方法:
方法 | 说明 |
---|---|
insert |
将一个新事实放入工作记忆中。 |
delete 或 retract
|
从工作内存中删除一些信息(对象)。 |
update |
更新/替换工作记忆中的一个事实。 |
modify |
更改工作记忆中事实中的字段。 |
这些方法还有一些“逻辑”版本,您可以在 Drools documentation 中阅读更多相关信息。
如果您在进行更改时或之后不使用这些内置框架方法,您将继续评估初始规则匹配集。这些变化实际上对 drools 来说是不可见的,因为你没有告诉 Drools “嘿,我们已经做出了改变”。每个规则的左侧都根据原始数据集进行了评估;根据匹配顺序对右侧进行评估。
因此,在您的情况下,您想要做的是使用 modify
函数告诉 Drools 您正在对工作记忆中的一条信息进行更改。
rule "test1"
when
$cr: MyContext(flag1 == 1)
then
modify( $cr ) {
setFlag1(10)
}
end
需要注意的一件事是如何评估规则匹配。当您调用 insert
将新数据放入工作内存时,Drools 将对规则匹配进行部分重新评估。已经匹配并执行过的规则不会再次运行;仅重新评估后续规则以确定它们现在是否匹配。
相反,update
将对所有规则进行全面评估。它的功能等同于停止当前规则执行并使用工作内存中的新数据调用 fireAllRules
。
如果您的规则具有外部副作用或不是幂等的,则调用 update
可能会产生严重的副作用,因为随着数据的变化,您可能会多次评估规则的 RHS。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。