目录
前面我们已经知道了规则体的构成如下:
rule "ruleName"
attributes
when
LHS
then
RHS
end
1、enable属性
enabled属性对应的取值为true和false,默认值为true。
用于指定当前规则是否启用,如果设置的值为false则当前规则无论是否匹配成功都不会触发。
rule "rule_comparison_notMemberOf"
//指定当前规则不可用,当前规则无论是否匹配成功都不会执行
enabled false
when
ComparisonOperatorEntity(names not memberOf list)
then
System.out.println("规则rule_comparison_notMemberOf触发");
end
2、dialect属性
dialect属性用于指定当前规则使用的语言类型,取值为java和mvel,默认值为java。
注:mvel是一种基于java语法的表达式语言。
mvel像正则表达式一样,有直接支持集合、数组和字符串匹配的操作符。
mvel还提供了用来配置和构造字符串的模板语言。
mvel表达式内容包括属性表达式,布尔表达式,方法调用,变量赋值,函数定义等。
3、salience属性
salience属性用于指定规则的执行优先级,取值类型为Integer。数值越大越优先执行。每个规则都有一个默认的执行顺序,如果不设置salience属性,规则体的执行顺序为由上到下。
可以通过创建规则文件salience.drl来测试salience属性,内容如下:
//当前规则文件用于测试执行优先级
package testsalience
//定义一个规则
rule "rule_1"
salience 10
when
eval(true)//返回true,即当前规则匹配成功
then
System.out.println("规则:rule_1触发了、、、");
end
//定义第二个规则
rule "rule_2"
salience 12
when
eval(true)//返回true,即当前规则匹配成功
then
System.out.println("规则:rule_2触发了、、、");
end
//定义第三个规则
rule "rule_3"
salience 11
when
eval(true)//返回true,即当前规则匹配成功
then
System.out.println("规则:rule3触发了、、、");
end
通过控制台可以看到,规则文件执行的顺序是按照我们设置的salience值由大到小顺序执行的。
建议在编写规则时使用salience属性明确指定执行优先级。
4、no-loop属性
no-loop属性用于防止死循环,当规则通过update之类的函数修改了Fact对象时,可能使当前规则再次被激活从而导致死循环。取值类型为Boolean,默认值为false。测试步骤如下:
第一步:编写规则文件/resource/rules/noloop.drl
package testnoloop
import com.itheima.drools.entity.Student
/*
此规则文件用于测试no-loop属性
*/
rule "rule_noloop"
no-loop true
when
$student:Student(age == 50)
then
update($student);//注意此处执行update会导致当前规则重新被激活
System.out.println("规则rule_noloop触发");
end
第二步:测试、、、、、、
5、activation-group属性
activation-group属性是指激活分组,取值为String类型。具有相同分组名称的规则只能有一个规则被触发。
第一步:编写规则文件/resources/rules/activationgroup.drl
//当前规则文件用于测试activation-group属性
package testactivationgroup
rule "rule_activationgroup_1"
activation-group "mygroup" //对于同一个组内的规则,只能有一个触发
salience 5
when
//如果条件不写,默认为true,表示规则匹配成功
then
System.out.println("规则: rule_activationgroup_1触发了、、、、");
end
rule "rule_activationgroup_2"
activation-group "mygroup"
salience 10
when
//如果条件不写,默认为true,表示规则匹配成功
then
System.out.println("规则: rule_activationgroup_2触发了、、、、");
end
第二步:编写单元测试
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();
通过控制台可以发现,上面的两个规则因为属于同一个分组,所以只有一个触发了。同一个分组中的多个规则如果都能够匹配成功,具体哪一个最终能够被触发可以通过salience属性确定。
6、agenda-group属性
agenda-group属性为议程分组,属于另一种可控的规则执行方式。用户可以通过设置agenda-group来控制规则的执行,只有获取焦点的组中的规则才会被触发。
第一步:创建规则文件/resources/rules/agendagroup.drl
package testagendagroup
/*
此规则文件用于测试agenda-group属性
*/
rule "rule_agendagroup_1"
agenda-group "myagendagroup_1"
when
then
System.out.println("规则rule_agendagroup_1触发");
end
rule "rule_agendagroup_2"
agenda-group "myagendagroup_1"
when
then
System.out.println("规则rule_agendagroup_2触发");
end
//========================================================
rule "rule_agendagroup_3"
agenda-group "myagendagroup_2"
when
then
System.out.println("规则rule_agendagroup_3触发");
end
rule "rule_agendagroup_4"
agenda-group "myagendagroup_2"
when
then
System.out.println("规则rule_agendagroup_4触发");
end
第二步:测试类
@Test
public void test5()
{
KieServices kieServices = KieServices.Factory.get();
//获得Kie容器对象
//默认自动加载 META-INF/kmodule.xml
//从KieServices中获得KieContainer实例,其会加载kmodule.xml文件并load规则文件
KieContainer kieContainer = kieServices.getKieClasspathContainer();
//从Kie容器对象中获取会话对象
KieSession session = kieContainer.newKieSession();
//设置焦点,对应agenda-group分组中的规则才可能被触发
session.getAgenda().getAgendaGroup("myagendagroup_2").setFocus();
session.fireAllRules();
session.dispose();
}
7、auto-focus属性
auto-focus属性为自动获取焦点,取值类型为Boolean,默认值为false。一般结合agenda-group属性使用,当一个议程分组未获取焦点时,可以设置auto-focus属性来控制。
第一步:修改/resources/rules/agendagroup.drl文件内容如下
package testagendagroup
/*
此规则文件用于测试agenda-group属性
*/
rule "rule_agendagroup_1"
agenda-group "myagendagroup_1"
auto-focus true //auto-focus属性用于指定当前所属组自动获取焦点
when
then
System.out.println("规则rule_agendagroup_1触发");
end
rule "rule_agendagroup_2"
agenda-group "myagendagroup_1"
when
then
System.out.println("规则rule_agendagroup_2触发");
end
//========================================================
rule "rule_agendagroup_3"
agenda-group "myagendagroup_2"
when
then
System.out.println("规则rule_agendagroup_3触发");
end
rule "rule_agendagroup_4"
agenda-group "myagendagroup_2"
when
then
System.out.println("规则rule_agendagroup_4触发");
end
8、timer属性
方式1
此种方式遵循java.util.Timer对象的使用方式,第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。
//当前规则文件用于测试timer属性
package testtimer
//timer第一种使用方式
rule "rule_timer_1"
timer(3s 2s) //当前timer属性用于指定规则触发的时间,当前表达式表示3s后触发,每隔2s触发一次
when
then
System.out.println("规则:rule_timer_1触发了、、、");
end
@Test
public void test5() throws InterruptedException
{
KieServices kieServices = KieServices.Factory.get();
//获得Kie容器对象
//默认自动加载 META-INF/kmodule.xml
//从KieServices中获得KieContainer实例,其会加载kmodule.xml文件并load规则文件
KieContainer kieContainer = kieServices.getKieClasspathContainer();
//从Kie容器对象中获取会话对象
final KieSession session = kieContainer.newKieSession();
new Thread(new Runnable()
{
public void run()
{
//启动规则引擎进行规则匹配,直到调用halt方法才结束规则引擎
session.fireUntilHalt();
}
}).start();
Thread.sleep(10000);
//结束规则引擎
session.halt();
session.dispose();
}
方式2
timer(cron: <cron expression>)
此种方式使用标准的unix cron表达式的使用方式来定义规则执行的时间。
第一步:创建规则文件/resources/rules/timer.drl
package testtimer
import java.text.SimpleDateFormat
import java.util.Date
/*
此规则文件用于测试timer属性
*/
rule "rule_timer_1"
timer (5s 2s) //含义:5秒后触发,然后每隔2秒触发一次
when
then
System.out.println("规则rule_timer_1触发,触发时间为:" +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
rule "rule_timer_2"
timer (cron:0/1 * * * * ?) //含义:每隔1秒触发一次
when
then
System.out.println("规则rule_timer_2触发,触发时间为:" +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end
第二步:编写单元测试
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
final KieSession kieSession = kieClasspathContainer.newKieSession();
new Thread(new Runnable() {
public void run() {
//启动规则引擎进行规则匹配,直到调用halt方法才结束规则引擎
kieSession.fireUntilHalt();
}
}).start();
Thread.sleep(10000);
//结束规则引擎
kieSession.halt();
kieSession.dispose();
注意:单元测试的代码和以前的有所不同,因为我们规则文件中使用到了timer进行定时执行,需要程序能够持续一段时间才能够看到定时器触发的效果。
9、date-effective属性
date-effective属性用于指定规则的生效时间,即只有当前系统时间大于等于设置的时间或者日期规则才有可能触发。默认日期格式为:dd-MMM-yyyy。用户也可以自定义日期格式。
第一步:编写规则文件/resources/rules/dateeffective.drl
package testdateeffective
/*
此规则文件用于测试date-effective属性
*/
rule "rule_dateeffective_1"
date-effective "2020-10-01 10:00"
when
then
System.out.println("规则rule_dateeffective_1触发");
end
第二步:编写单元测试
//设置日期格式
System.setProperty("drools.dateformat","yyyy-MM-dd HH:mm");
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();
注意:上面的代码需要设置日期格式,否则我们在规则文件中写的日期格式和默认的日期格式不匹配程序会报错。
10、date-expires属性
date-expires属性用于指定规则的失效时间,即只有当前系统时间小于设置的时间或者日期规则才有可能触发。默认日期格式为:dd-MMM-yyyy。用户也可以自定义日期格式。
第一步:编写规则文件/resource/rules/dateexpires.drl
package testdateexpires
/*
此规则文件用于测试date-expires属性
*/
rule "rule_dateexpires_1"
date-expires "2019-10-01 10:00"
when
then
System.out.println("规则rule_dateexpires_1触发");
end
第二步:编写单元测试
//设置日期格式
System.setProperty("drools.dateformat","yyyy-MM-dd HH:mm");
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();
注意:上面的代码需要设置日期格式,否则我们在规则文件中写的日期格式和默认的日期格式不匹配程序会报错。