我在使用org.drools.compiler.lang.api提供的RuleDescrBuilder API构建的DrL文件中使用以下结构。
我触发一个匹配后事件,以跟踪后端中每个规则的命中数。但是,当输入(Predicate)匹配Rule1中的所有给定条件时,它会为一个输入触发多个afterMatchFiredEvents。
import com.objects.Predicate
global com.Util policyUtil
dialect "java"
rule "Rule1:RuleId"
salience 2147483647
when
predicate := Predicate( )
(
eval( policyUtil.evaluate(condition1) ) or
eval( policyUtil.evaluate(condition2) ) or
eval( policyUtil.evaluate(condition3) )
then
...
end
rule "defaultRule:defaultRule"
salience 0
when
predicate := Predicate( )
then
predicate.setValue1("default1");
predicate.setValue2("Default2");
drools.halt();
end
这是赛后事件触发器:
public void afterMatchFired(AfterMatchFiredEvent event) {
logger.info("Matching rule Name:: " + event.getMatch().getRule().getName());
updateHitCountForRule(event.getMatch().getRule().getName());
}
这就是使用ruledescbuilder的方式。
RuleDescrBuilder rdb = pdb.newRule();
CEDescrBuilder<?, ?> cedb = rdb.lhs();
cedb = cedb.and();
for(each condition in rule)
cedb.eval().constraint(constraint).end();
问:为什么对于具有OR条件的相同规则,afterMatchFired多次触发?我假设没有正确使用eval。如果未正确使用eval,使用上述方法构建此类规则集的正确方法是什么?
答案 0 :(得分:1)
这是因为Drools在模式之间处理or
运算符的方式。幕后发生的事情是Drools根据您的原始规则创建了3条不同的规则:
rule "Rule1:RuleId 1"
salience 2147483647
when
predicate := Predicate( )
eval( policyUtil.evaluate(condition1) )
then
...
end
rule "Rule1:RuleId 2"
salience 2147483647
when
predicate := Predicate( )
eval( policyUtil.evaluate(condition2) )
then
...
end
rule "Rule1:RuleId 3"
salience 2147483647
when
predicate := Predicate( )
eval( policyUtil.evaluate(condition3) )
then
...
end
如您所见,Drools中的模式之间没有短路or
运算符。如果您的所有eval
都匹配,则您不仅会收到AfterMatchFiredEvent
3次,而且您的规则的action
部分也会被执行3次。
避免这种情况的一种可能方法(即使它有点hacky)是使用事实作为标志来避免多次执行action
部分:
rule "Rule1:RuleId"
salience 2147483647
when
not RuleExecuted()
predicate := Predicate( )
(
eval( policyUtil.evaluate(condition1) ) or
eval( policyUtil.evaluate(condition2) ) or
eval( policyUtil.evaluate(condition3) )
)
then
...
insert(new RuleExecuted());
end
在这种情况下,您仍会在听众中收到3个BeforeMatchFiredEvent
个事件,但只有1个AfterMatchFiredEvent
。您也将收到2个MatchCancelledEvent
个活动。
希望它有所帮助,