我有一个对象如下:
class License{
private field1;
private field2;
private boolean active;
private String activeMessage;
private boolean processed = false;
//Getter and setter methods
}
Run Code Online (Sandbox Code Playgroud)
我想做的是,根据 field1 和 field2 的值,我需要设置 isActive 标志和相应的消息。但是,如果 field1 或 field2 的规则被触发,我需要停止规则处理。也就是说,我只需要执行 1 条成功的规则。
我在一篇文章中读到,执行 ksession.fireAllRules(1) 将解决此问题。但是 fireAllRules() 方法在 Drools 6 中不可用。我也尝试输入一个返回;每条规则末尾的声明。那对我也没有帮助。
最后,我最终向我的对象添加了一个名为“processed”的附加字段。因此,每当我执行任何规则时,我都会将已处理标志设置为 true。如果该标志已经设置,那么我不会执行任何规则。这是我的规则文件:
rule "Check field1"
when
$obj : License(getField1() == "abc" && isProcessed() == false)
then
System.out.println("isProcessed >>>>>> "+$obj.isProcessed());
$obj.setActive(true);
$order.setActiveMessage("...");
$order.setProcessed(true);
end
rule "Check field2"
when
$obj : License(getField2() == "def" && isProcessed() == false)
then
System.out.println("isProcessed >>>>>> "+$obj.isProcessed());
$obj.setActive(true);
$order.setActiveMessage("...");
$order.setProcessed(true);
end
Run Code Online (Sandbox Code Playgroud)
然而,我发现即使现在我的两条规则都被解雇了。当我尝试打印 isProcessed() 的值时,它显示 true,即使我仅在 isProcessed() 为 false 时输入规则。
这就是我调用 drools 引擎的方式:
kieService = KieServices.Factory.get();
kContainer = kieService.getKieClasspathContainer();
kSession = kContainer.newStatelessKieSession();
kSession.execute(licenseObj);
Run Code Online (Sandbox Code Playgroud)
它不仅仅是2条规则,我有很多规则,因此通过更改drl文件中规则的顺序来控制规则执行不是一个选项。这里发生了什么?我怎么解决这个问题?我对 Drools 有点陌生,所以我可能在这里遗漏了一些东西。
谢谢。
您的问题包含许多错误。
这绝对不是真的,它fireAllRules
在 Drools 6 中消失了。您可能已经查看了 javadoc 索引,在接口的包中找到了此方法的四个 (4!) 重载org.kie.api.runtime.rule
版本StatefulRuleSession
。
通过组合触发约束,您可以轻松避免仅触发两个规则之一的问题:
rule "Check field1 and field2"
when
$lic: License(getField1() == "abc" || getField2() == "def" )
//...
then
$lic.setXxx(...);
end
Run Code Online (Sandbox Code Playgroud)
你抱怨说,尽管processed
在事实中设置了标志,但你的两条规则都被触发了。这里你忽略了一个基本点(Drools 参考手册中对此进行了介绍),即每当你更改事实数据时通知引擎的必要性。您应该modify
在规则的右侧使用。
但即便如此也还不够好。每当由于某些属性而进行更新时,都应该添加约束以避免一遍又一遍地运行更新。你可能已经写过:
rule "Check field1 and field2"
when
$lic: License(getField1() == "abc" || getField2() == "def",
! active )
//...
then
modify( $lic ){ setActive( true ) }
end
Run Code Online (Sandbox Code Playgroud)
您甚至可以将其写成两个不同的规则,每个字段一个,并且这些规则中只有一个会触发......