场景
当我们使用activation-group时,默认会执行优先级最高的一个规则,然后其他规则不再执行,这也是此属性的基本特性。那么,大家是否考虑过这样一个问题,那就是如果在调用fireAllRules方法之前,insert了多个对象,那么应该触发几次规则?
在其他属性的使用时,我们知道,如果插入多个对象,那么如果每个对象都符合同一规则条件就会执行多次,如果部分条件符合规则,就执行部分次。当我们即想使用activation-group的特性,又想实现上面的要求时改如何去做呢?
实例解析
实例一
首先,我们来确认第一个问题,insert多个FACT对象,会触发几次规则。
@Test
public void testRules() {
KieServices ks = KieServices.Factory.get();
KieContainer kieContainer = ks.getKieClasspathContainer();
KieSession kSession = kieContainer.newKieSession("ksession-rule");
kSession.getAgenda().getAgendaGroup("foo").setFocus();
Product p2 = new Product();
p2.setDiscount(20);
Product p1 = new Product();
p1.setDiscount(10);
kSession.insert(p2);
kSession.insert(p1);
int count = kSession.fireAllRules();
System.out.println("第一次执行命中了" + count + "条规则!");
kSession.dispose();
}
package com.rules
import com.secbro.drools.model.Product
rule "test-activation-group1"
activation-group "foo"
when
$obj : Product()
then
System.out.println("test-activation-group1 被触发");
end
rule "test-activation-group2"
activation-group "foo"
salience 1
when
$obj : Product()
then
System.out.println("test-activation-group2 被触发 discount= " + $obj.getDiscount());
end
执行的结果如下:
test-activation-group2 被触发 discount= 10 第一次执行命中了1条规则!
很显然,插入了两个FACT对象,只触发了一次规则。
实例二
那么,我们想达到上面说的,如果插入多个对象,每个符合条件的都触发一次,同时一个activation-group组中只触发优先级比较高的。
这就需要我们修改改代码如下:
@Test
public void testRules() {
KieServices ks = KieServices.Factory.get();
KieContainer kieContainer = ks.getKieClasspathContainer();
KieSession kSession = kieContainer.newKieSession("ksession-rule");
kSession.getAgenda().getAgendaGroup("foo").setFocus();
Product p2 = new Product();
p2.setDiscount(20);
kSession.insert(p2);
int count = kSession.fireAllRules();
System.out.println("第一次执行命中了" + count + "条规则!");
Product p1 = new Product();
p1.setDiscount(10);
kSession.insert(p1);
count = kSession.fireAllRules();
System.out.println("第一次执行命中了" + count + "条规则!");
kSession.dispose();
}
执行结果:
test-activation-group2 被触发 discount= 20 第一次执行命中了1条规则! test-activation-group2 被触发 discount= 10 第一次执行命中了1条规则!
像上面这样,每执行一次调用一次fireAllRules就达到了预期的目的。
另外一种方式就是不使用activation-group方法,而采用delete方法。
@Test
public void testRules() {
KieServices ks = KieServices.Factory.get();
KieContainer kieContainer = ks.getKieClasspathContainer();
KieSession kSession = kieContainer.newKieSession("ksession-rule");
kSession.getAgenda().getAgendaGroup("foo").setFocus();
Product p2 = new Product();
p2.setDiscount(20);
kSession.insert(p2);
Product p1 = new Product();
p1.setDiscount(10);
kSession.insert(p1);
int count = kSession.fireAllRules();
System.out.println("第一次执行命中了" + count + "条规则!");
kSession.dispose();
}
package com.rules
import com.secbro.drools.model.Product
rule "test-activation-group1" // activation-group "foo"
when
$obj : Product()
then
delete($obj)
System.out.println("test-activation-group1 被触发");
end
rule "test-activation-group2" // activation-group "foo"
salience 1
when
$obj : Product()
then
delete($obj)
System.out.println("test-activation-group2 被触发 discount= " + $obj.getDiscount());
end
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/15188.html