1.概述
数据插入到工作内存(working memory)后,会触发所有规则的匹配,并执行完全匹配的规则。当数据完全匹配规则的时候,规则引擎会创建一个activation instance,并引用该rule和与之匹配的数据(也就是说多条数据与同一rule完全匹配时,会创建多个activation instance,这一点对于之后理解规则遍历集合很重要),然后添加到agenda中。Agenda根据冲突策略决定activation instance的执行顺序。
规则引擎分两个工作步骤:
- agenda evaluation: 收集所有可执行的rule 和数据并在agenda中注册activation instance,然后进入 working memory actions阶段,执行rule中的consequence语句(即then)。
- working memory actions: 执行注册在agenda中的activation,然后重新回到agenda evaluation阶段。
2.冲突解决策略
•salience
rule的属性之一,值为整型数值,支持正数或负数,默认值为0,用于设置规则执行的优先级,其值越大,优先级越高。
•agenda groups
可将一个或一个以上的rule设置为同一个agenda-group分组,默认分组为”MAIN”。只有获得焦点的分组才会被匹配执行,同一时间只有一个分组可以获得焦点,默认main分组持有焦点,可以使用auto-focus属性或者setFocus()方法将焦点分配给分组,auto-focus属性为true时会自动获取焦点,且优先级高于setFocus()方法(值为false时则不影响),当auto-focus属性为true 且setFocus()时,优先级高于仅auto-focus属性为true的分组;按setFocus()按倒序顺序,最后调用该方法的优先级较高;main分组最终会获得焦点;其他声明了agenda-group属性,但未分配焦点的不会发生规则匹配和执行(不完全匹配的规则不会执行then,但会执行when,这里未获得焦点,when都不会执行,这点对于规则性能方面的优化很重要)。
举例:
java代码:
KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
KieSession kieSession = kc.newKieSession();
//获取agenda
Agenda agenda = kieSession.getAgenda();
//设置焦点,以下执行顺序为ag_2,ag_1,main
agenda.getAgendaGroup("ag_1").setFocus();
agenda.getAgendaGroup("ag_2").setFocus();
//移除main分组的焦点
//agenda.getAgendaGroup("MAIN").clear();
kieSession.fireAllRules();
drl文件:
//以下内容实际是遵循DRL语法写的,这里编辑设置为java只是为了好看。
//以下rules排版乱序,主要是为了排除rule位置顺序的干扰,顺序可以按照自己意愿排版。
function Boolean test(){
//用于调试, rule when 中调用该function,打印信息,用于证明规则执行了匹配
System.out.println("function excue");
return true;
}
function Boolean test1(){
//用于调试,rule when 中调用该function,打印信息,用于证明规则执行了匹配
System.out.println("test1 excue");
return false;
}
rule rule_4
agenda-group "ag_4"
auto-focus true
when
// eval(test1())
eval(test())
then
System.out.println("agenda-group_4 ");
end
rule rule_3
when
eval(true)
then
System.out.println("agenda-group_main");
end
rule rule_1
agenda-group "ag_1"
when
eval(true)
then
System.out.println("agenda-group_1");
insert(true);
end
rule rule_5
agenda-group "ag_2"
//activation-group "acg_1"
auto-focus
when
eval(true)
then
System.out.println("agenda-group_2_rule_5");
end
rule rule_2
agenda-group "ag_2"
auto-focus
//activation-group "acg_1"
//salience 10
when
eval(true)
then
System.out.println("agenda-group_2");
end
执行结果如下:
function excue
agenda-group_2_rule_5
agenda-group_2
agenda-group_4
agenda-group_1
agenda-group_main
说明:以上执行结果中function excue排在最前边,是因为drools执行顺序是先运行所有rule的when,最后再按顺序执行then。
删除rule_4的 auto-focus 属性,由于未给rule_4分配焦点,所以rule_4未执行,运行结果如下:
agenda-group_2_rule_5
agenda-group_2
agenda-group_1
agenda-group_main
可以调用clear()方法在分组匹配执行前取消焦点,例如: agenda.getAgendaGroup("MAIN").clear();。
•activation groups
可以将一个或多个rule设置为同一个activation-group分组,当分组中有全匹配的规则,则仅执行agenda中该分组中优先级最高的rule,其他都从agenda中移除。
上例中 rule_5 和 rule_2 增加属性activation-group "acg_1" ,rule_2增加属性 salience 10,rule_5和rule_2均为全匹配规则,由于在同一个activation-group 分组中,所以仅执行其中一个,因为rule_2的优先级更高,所以rule_2执行了,rule_5未被执行。运行结果如下:
agenda-group_2
agenda-group_1
agenda-group_main