drools规则编写内置几个关键字
drools语法关于关于规则执行互斥分组以及相关的关键字如下
agenda-group:规则是否执行的分组,同一个分组的规则要么都执行要么都不执行
salience:执行顺序优先级
activation-group:互斥的规则分组,同一组的规则只有一条会被执行,其他不执行(事实对象修改被显示通知drools的除外)
用来对规则进行分组的标签
对于带有agenda-group的规则,如果所在分组中某个规则带有auto-focus标签,则分组包含的规则在规则引擎中会被执行;否则不会执行。
对于没有agenda-group标签的规则,则不受到auto-focus标签的影响,会被执行。
示例:
主函数
public static void main(String[] args) {
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("testSession");
kieSession.setGlobal("results", Lists.newArrayList());
Map paramMap = Maps.newHashMap();
paramMap.put("key","3");
kieSession.insert(paramMap);
kieSession.fireAllRules();
}
规则组1
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule1-a"
agenda-group "001"
auto-focus
when
$param:Map(key==3)
then
System.out.println("testRule1-a");
results.add("break");
end
rule "testRule1-b"
agenda-group "001"
when
$param:Map(key==3)
then
System.out.println("testRule1-b");
results.add("break");
end
以下放入到第二个文件中
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule3"
agenda-group "001"
when
$param:Map(key==3)
then
System.out.println("testRule3");
results.add("break");
end
规则组2未加auto-focus
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule2-a"
agenda-group "002"
when
$param:Map(key==3)
then
System.out.println("testRule2-a");
results.add("continue");
end
rule "testRule2-b"
agenda-group "002"
when
$param:Map(key==3)
then
System.out.println("testRule2-b");
results.add("continue");
end
第三组规则另一个带有auto-focus的分组
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule"
agenda-group "005"
auto-focus
when
$param:Map(key==3)
then
System.out.println("testRule5");
results.add("break");
end
第四组规则,未加agenda-group
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule4"
when
$param:Map(key==3)
then
System.out.println("testRule4");
results.add("break");
end
可以看出
agenda-group为003的规则存在auto-focus,被执行,输出
testRule3
agenda-group为001的规则也存在auto-focus,被执行,输出
testRule1-a
testRule1-b
执行另一个带有auto-focus的分组
输出testRule5
最后执行不包含agenda-group标签的testRule4,输出
testRule4
用来指定规则的执行顺序的优先级,数值越大优先级越高,执行顺序越靠前,默认值为0,可以为负数
例子:
第一组
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule1-a"
agenda-group "001"
auto-focus
salience 0
when
$param:Map(key==3)
then
System.out.println("testRule1-a");
results.add("break");
end
rule "testRule1-b"
agenda-group "001"
salience 50
when
$param:Map(key==3)
then
System.out.println("testRule1-b");
results.add("break");
end
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule3"
agenda-group "001"
auto-focus
salience 20
when
$param:Map(key==3)
then
System.out.println("testRule3");
results.add("break");
end
第二组
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule2-a"
agenda-group "002"
salience 10
when
$param:Map(key==3)
then
System.out.println("testRule2-a");
results.add("continue");
end
rule "testRule2-b"
agenda-group "002"
salience 40
auto-focus
when
$param:Map(key==3)
then
System.out.println("testRule2-b");
results.add("continue");
end
第三组
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule4"
salience 20
when
$param:Map(key==3)
then
System.out.println("testRule4");
results.add("break");
end
可以看出,执行规则的顺序为按组执行,执行完001 这个group再执行002这个group,最后再执行没有分组的规则,并且优先级是按照组内的优先级执行,并不能跨组优先级
综上所述,执行的顺序是先按分组
1.被focus的agenda-group所包含的规则
2.然后没有agenda-group的规则
之后按每个分组内部的salience优先级顺序,先执行值大的规则,再执行值小的规则
同一个activation-group的规则是互斥的,只有一个会被执行。
(注意,如果被执行的规则存在调用insert,modify,update 等方法,互斥的唯一性将被打破,需要再次调用下一个规则,一直执行下去直到没有通知drools 事实对象被修改的规则(即不包含insert,modify,update 等方法),详细用例见触发规则重复执行)
示例:
规则代码一组
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule1-a"
agenda-group "001"
auto-focus
activation-group "act001"
salience 0
when
$param:Map(key==3)
then
System.out.println("testRule1-a");
results.add("break");
end
rule "testRule1-b"
agenda-group "001"
activation-group "act001"
salience 50
when
$param:Map(key==3)
then
System.out.println("testRule1-b");
results.add("break");
end
规则代码二组
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule2-a"
agenda-group "002"
auto-focus
activation-group "act001"
salience 10
when
$param:Map(key==3)
then
System.out.println("testRule2-a");
results.add("continue");
end
可以看出activation-group同为001的三个规则,只执行了一个。
如果被执行的规则存在
update modify insert等修饰事实对象的操作
则有可能出现循环重复执行的情况
例子:
代码
package rules;
import java.util.List;
import java.util.Map;
global java.util.List results;
rule "testRule1-a"
activation-group "act001"
//no-loop true
when
$param:Map(key==3)
then
System.out.println(" testRule1-a");
$param.put("key",4);
update($param);
results.add("break");
end
rule "testRule2-a"
//no-loop true
when
$param:Map(key==4)
then
System.out.println(" testRule2-a");
$param.put("key",5);
update($param);
results.add("continue");
end
rule "testRule1-b"
activation-group "act001"
//no-loop true
when
$param:Map(key==5)
then
System.out.println(" testRule1-b");
$param.put("key",3);
update($param);
results.add("break");
end
解决方案就是去掉一个update() 断开循环链