drools中的事实传播模式
drools支持下面的事实传播模式,这些模式决定了drools如何通过引擎网络推进插入的事实,用来为执行规则做准备:
- Lazy(延迟模式):(默认) 事实在规则执行时在批量集合中传播,而不是作为插入的单条事实去实时传播。因此,事实最终的传播顺序,和事实插入的顺序是不一样的。
- Immediate(立即模式):事实会立即传播,而且事实传播的顺序就是事实插入时的顺序。
- Eager(急切模式):事实被延迟传播(在批处理集合中),但是是在规则执行之前。drools的这种传播行为是为了那些设置了no-loop或者lock-on-active属性的规则。
默认的,为了全面提高规则评估,drools的Phreak规则算法使用懒加载事实传播。但是,在少数情况下,懒加载能改变某些规则执行的预期结果,这些规则执行就需要立即传播或者eager传播。
例如,下面的规则用?前缀的指定查询,用来仅拉取或被动方式调用查询:
使用被动查询规则的示例
query Q (Integer i)
String( this == i.toString() )
end
rule "Rule"
when
$i : Integer()
?Q( $i; )
then
System.out.println( $i );
end
对于这个例子,在插入整数之前,只有当插入满足查询的字符串时,规则才会被执行,例如下面的示例命令:
触发规则执行的示例命令
KieSession ksession = ...
ksession.insert("1");
ksession.insert(1);
ksession.fireAllRules();
但是,由于在Phreak中默认的传播行为是懒加载,drools没有检测到两个事实的插入顺序,所以,不论字符串和整数的插入顺序如何,这个规则都会执行。对于这个例子,为了预期的规则评估,需要立即传播。
在这个情况下,为了完成预期的规则评估,更改drools的传播模式,你可以在你的规则上添加@Propagation(
这相同的示例规则下,立即传播注解能够像预期的那样执行规则评估:
使用被动查询和指定传播模式的规则示例
query Q (Integer i)
String( this == i.toString() )
end
rule "Rule" @Propagation(IMMEDIATE)
when
$i : Integer()
?Q( $i; )
then
System.out.println( $i );
end
议程评估过滤器
图示5.议程过滤器
drools在过滤器接口中支持AgendaFilter对象,在议程评估阶段,这个对象可以允许或者拒绝指定规则的评估。你可以指定一个议程过滤器作为fireAllRules方法调用的一部分。
下面的实例代码 只允许带有字符串"Test"结尾的规则被评估和执行。所有其他的规则都会被过滤器过滤掉。
议程过滤器的定义示例
ksession.fireAllRules( new RuleNameEndsWithAgendaFilter( "Test" ) );