目录
前面我们已经知道了规则体的构成如下:
rule "ruleName"
attributes
when
LHS
then
RHS
end
本章节就是针对规则体的attributes属性部分进行讲解。Drools中提供的属性如下表(部分属性):
enabled属性对应的取值为true和false,默认值为true。
用于指定当前规则是否启用,如果设置的值为false则当前规则无论是否匹配成功都不会触发。
在/resources/rules下创建规则文件attributes-enabled.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesEnabledEntity
/*
用于测试Drools 属性:enabled
*/
//测试enabled
rule "rule_attributes_enabled"
enabled false
when
AttributesEnabledEntity(num > 10)
then
System.out.println("规则rule_attributes_enabled触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/17 18:16:40
* @description enabled属性实体
*/
@Data
public class AttributesEnabledEntity {
private int num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesEnabledEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/17 18:23:37
* @description enable属性测试类
*/
public class AttributesEnabledTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test() {
KieSession kieSession = kieBase.newKieSession();
AttributesEnabledEntity attributesEnabledEntity = new AttributesEnabledEntity();
attributesEnabledEntity.setNum(20);
kieSession.insert(attributesEnabledEntity);
kieSession.fireAllRules();
kieSession.dispose();
}
}
我们发现,当我们的enable属性设置为false时,并没有触发规则。
接下来我们设置enable属性设置为true,看下测试结果:
我们发现,触发了规则。
dialect属性用于指定当前规则使用的语言类型,取值为java和mvel,默认值为java。
虽然mvel吸收了大量的java语法,但作为一个表达式语言,还是有着很多重要的不同之处,以达到更高的效率,比如:mvel像正则表达式一样,有直接支持集合、数组和字符串匹配的操作符。除了表达式语言外,mvel还提供了用来配置和构造字符串的模板语言。mvel2.x表达式包含以下部分的内容:属性表达式,布尔表达式,方法调用,变量赋值,函数定义。
注:mvel是一种基于java语法的表达式语言。
salience属性用于指定规则的执行优先级,取值类型为Integer。数值越大越优先执行。每个规则都有一个默认的执行顺序,如果不设置salience属性,规则体的执行顺序为由上到下。
在/resources/rules下创建规则文件attributes-salience.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesSalienceEntity
/*
用于测试Drools 属性:salience
*/
rule "rule_attributes_salience_1"
salience 10
when
AttributesSalienceEntity(flag == true)
then
System.out.println("规则 rule_attributes_salience_1 触发");
end
rule "rule_attributes_salience_2"
salience 20
when
AttributesSalienceEntity(flag == true)
then
System.out.println("规则 rule_attributes_salience_2 触发");
end
rule "rule_attributes_salience_3"
salience 1
when
AttributesSalienceEntity(flag == true)
then
System.out.println("规则 rule_attributes_salience_3 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/17 18:39:02
* @description salience 属性实体
*/
@Data
public class AttributesSalienceEntity {
private Boolean flag;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesSalienceEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/17 18:41:03
* @description salience 属性测试类
*/
public class AttributesSalienceTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test() {
KieSession kieSession = kieBase.newKieSession();
AttributesSalienceEntity attributesSalienceEntity = new AttributesSalienceEntity();
attributesSalienceEntity.setFlag(true);
kieSession.insert(attributesSalienceEntity);
kieSession.fireAllRules();
kieSession.dispose();
}
}
通过控制台可以看到,规则文件执行的顺序是按照我们设置的salience值由大到小顺序执行的。建议在编写规则时使用salience属性明确指定执行优先级。
no-loop属性用于防止死循环,当规则通过update之类的函数修改了Fact对象时,可能使当前规则再次被激活从而导致死循环。取值类型为Boolean,默认值为false。
在/resources/rules下创建规则文件attributes-noloop.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesNoLoopEntity
/*
用于测试Drools 属性:no-loop
*/
rule "rule_attributes_noloop"
no-loop true
when
$attributesNoLoopEntity:AttributesNoLoopEntity(num > 1)
then
update($attributesNoLoopEntity)
System.out.println("规则 rule_attributes_noloop 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/17 18:52:25
* @description no-loop属性实体
*/
@Data
public class AttributesNoLoopEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesNoLoopEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/17 18:53:34
* @description no-loop属性测试类
*/
public class AttributesNoLoopTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test() {
KieSession kieSession = kieBase.newKieSession();
AttributesNoLoopEntity attributesNoLoopEntity = new AttributesNoLoopEntity();
attributesNoLoopEntity.setNum(20);
kieSession.insert(attributesNoLoopEntity);
kieSession.fireAllRules();
kieSession.dispose();
}
}
可以看到,当属性no-loop为false 时,规则一直在循环触发。我们修改no-loop为true,再看下测试结果。
接下来设置no-loop的值为true再次测试则不会发生死循环。
lock-on-active这个属性,可以限制当前规则只会被执行一次,包括当前规则的重复执行不是本身触发的。取值类型为Boolean,默认值为false。
在/resources/rules下创建规则文件attributes-lock-on-active.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesLockOnActiveEntity
/*
用于测试Drools 属性:lock-on-active
*/
rule "rule_attributes_lock_on_active_1"
no-loop true
when
$attributesLockOnActiveEntity:AttributesLockOnActiveEntity(num > 1)
then
update($attributesLockOnActiveEntity)
System.out.println("规则 rule_attributes_lock_on_active_1 触发");
end
rule "rule_attributes_lock_on_active_2"
no-loop true
lock-on-active true
when
$attributesLockOnActiveEntity:AttributesLockOnActiveEntity(num > 1)
then
update($attributesLockOnActiveEntity)
System.out.println("规则 rule_attributes_lock_on_active_2 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/17 22:06:54
* @description lock-on-active属性实体
*/
@Data
public class AttributesLockOnActiveEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesLockOnActiveEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/17 22:08:39
* @description lock-on-active 属性测试类
*/
public class AttributesLockOnActiveTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test() {
KieSession kieSession = kieBase.newKieSession();
AttributesLockOnActiveEntity attributesLockOnActiveEntity = new AttributesLockOnActiveEntity();
attributesLockOnActiveEntity.setNum(20);
kieSession.insert(attributesLockOnActiveEntity);
kieSession.dispose();
}
}
当设置lock-on-active属性值为false时,我们看到,两个规则在循环触发,接下来我们设置lock-on-active属性值为true,看下测试结果。
no-loop的作用是限制因为modify等更新操作导致规则重复执行,但是有一个限定条件,是当前规则中进行更新导致当前规则重复执行。而不是防止其他规则更新相同的fact对象,导致当前规则更新,lock-on-active可以看作是no-loop的加强版,不仅能限制自己的更新,还能限制别人的更新造成的死循环。
activation-group属性是指激活分组,取值为String类型。具有相同分组名称的规则只能有一个规则被触发。
在/resources/rules下创建规则文件attributes-activation-group.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesActivationGroupEntity
/*
用于测试Drools 属性: activation-group
*/
rule "rule_attributes_activation_group_1"
activation-group "customActivationGroup"
when
$attributesActivationGroupEntity:AttributesActivationGroupEntity(num > 1)
then
System.out.println("规则 rule_attributes_activation_group_1 触发");
end
rule "rule_attributes_activation_group_2"
activation-group "customActivationGroup"
when
$attributesActivationGroupEntity:AttributesActivationGroupEntity(num > 1)
then
System.out.println("规则 rule_attributes_activation_group_2 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/18 12:03:38
* @description activation-group属性实体
*/
@Data
public class AttributesActivationGroupEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesActivationGroupEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/18 12:06:34
* @description activation-group属性测试类
*/
public class AttributesActivationGroupTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test(){
KieSession kieSession = kieBase.newKieSession();
AttributesActivationGroupEntity attributesActivationGroupEntity = new AttributesActivationGroupEntity();
attributesActivationGroupEntity.setNum(20);
kieSession.insert(attributesActivationGroupEntity);
kieSession.fireAllRules();
kieSession.dispose();
}
}
通过控制台可以发现,上面的两个规则因为属于同一个分组,所以只有一个触发了。同一个分组中的多个规则如果都能够匹配成功,具体哪一个最终能够被触发可以通过salience属性确定。
agenda-group属性为议程分组,属于另一种可控的规则执行方式。用户可以通过设置agenda-group来控制规则的执行,只有获取焦点的组中的规则才会被触发。
在/resources/rules下创建规则文件attributes-agenda-group.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesAgendaGroupEntity
/*
用于测试Drools 属性: agenda-group
*/
rule "rule_attributes_agenda_group_1"
agenda-group "customAgendaGroup1"
when
$attributesAgendaGroupEntity:AttributesAgendaGroupEntity(num > 1)
then
System.out.println("规则 rule_attributes_agenda_group_1 触发");
end
rule "rule_attributes_agenda_group_2"
agenda-group "customAgendaGroup1"
when
$attributesAgendaGroupEntity:AttributesAgendaGroupEntity(num > 1)
then
System.out.println("规则 rule_attributes_agenda_group_2 触发");
end
rule "rule_attributes_activation_group_3"
agenda-group "customAgendaGroup2"
when
$attributesAgendaGroupEntity:AttributesAgendaGroupEntity(num > 1)
then
System.out.println("规则 rule_attributes_activation_group_3 触发");
end
rule "rule_attributes_agenda_group_4"
agenda-group "customAgendaGroup2"
when
$attributesAgendaGroupEntity:AttributesAgendaGroupEntity(num > 1)
then
System.out.println("规则 rule_attributes_agenda_group_4 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/18 12:17:11
* @description agenda-group 属性实体
*/
@Data
public class AttributesAgendaGroupEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesAgendaGroupEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/18 12:15:41
* @description agenda-group 属性测试类
*/
public class AttributesAgendaGroupTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test(){
KieSession kieSession = kieBase.newKieSession();
AttributesAgendaGroupEntity attributesAgendaGroupEntity = new AttributesAgendaGroupEntity();
attributesAgendaGroupEntity.setNum(20);
kieSession.insert(attributesAgendaGroupEntity);
kieSession.getAgenda().getAgendaGroup("customAgendaGroup2").setFocus();
kieSession.fireAllRules();
kieSession.dispose();
}
}
通过控制台可以看到,只有获取焦点的分组中的规则才会触发。与activation-group不同的是,activation-group定义的分组中只能够有一个规则可以被触发,而agenda-group分组中的多个规则都可以被触发。
auto-focus属性为自动获取焦点,取值类型为Boolean,默认值为false。一般结合agenda-group属性使用,当一个议程分组未获取焦点时,可以设置auto-focus属性来控制。
在/resources/rules下创建规则文件attributes-auto-focus.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesAutoFocusEntity
/*
用于测试Drools 属性: auto-focus
*/
rule "rule_attributes_auto_focus_1"
agenda-group "customAgendaGroup1"
when
$attributesAutoFocusEntity:AttributesAutoFocusEntity(num > 1)
then
System.out.println("规则 rule_attributes_auto_focus_1 触发");
end
rule "rule_attributes_auto_focus_2"
agenda-group "customAgendaGroup1"
when
$attributesAutoFocusEntity:AttributesAutoFocusEntity(num > 1)
then
System.out.println("规则 rule_attributes_auto_focus_2 触发");
end
rule "rule_attributes_auto_focus_3"
agenda-group "customAgendaGroup2"
auto-focus true
when
$attributesAutoFocusEntity:AttributesAutoFocusEntity(num > 1)
then
System.out.println("规则 rule_attributes_auto_focus_3 触发");
end
rule "rule_attributes_auto_focus_4"
agenda-group "customAgendaGroup2"
when
$attributesAutoFocusEntity:AttributesAutoFocusEntity(num > 1)
then
System.out.println("规则 rule_attributes_auto_focus_4 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/18 19:55:59
* @description auto-focus属性实体
*/
@Data
public class AttributesAutoFocusEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesAutoFocusEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/18 19:57:15
* @description auto-focus属性测试类
*/
public class AttributesAutoFocusTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test() {
KieSession kieSession = kieBase.newKieSession();
AttributesAutoFocusEntity attributesAutoFocusEntity = new AttributesAutoFocusEntity();
attributesAutoFocusEntity.setNum(20);
kieSession.insert(attributesAutoFocusEntity);
kieSession.fireAllRules();
kieSession.dispose();
}
}
通过控制台可以看到,设置auto-focus属性为true的规则都触发了。
注意:同一个组,只要有个设置auto-focus true 其他的设置不设置都无所谓啦。都会起作用的。
timer属性可以通过定时器的方式指定规则执行的时间,使用方式有两种:
方式一:timer (int: ?)
此种方式遵循java.util.Timer对象的使用方式,第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。
方式二:timer(cron: )
此种方式使用标准的unix cron表达式的使用方式来定义规则执行的时间。
在/resources/rules下创建规则文件attributes-timer.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesTimerEntity
/*
用于测试Drools 属性: timer
*/
rule "rule_attributes_timer_1"
timer(5s 2s)
when
$attributesTimerEntity:AttributesTimerEntity(num > 1)
then
System.out.println("规则 rule_attributes_timer_1 触发");
end
rule "rule_attributes_timer_2"
timer(cron:0/1 * * * * ?)
when
$attributesTimerEntity:AttributesTimerEntity(num > 1)
then
System.out.println("规则 rule_attributes_timer_2 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/18 20:08:45
* @description time属性实体
*/
@Data
public class AttributesTimerEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesTimerEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/18 20:07:15
* @description time属性测试类
*/
public class AttributesTimerTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test() throws InterruptedException {
KieSession kieSession = kieBase.newKieSession();
AttributesTimerEntity attributesTimerEntity = new AttributesTimerEntity();
attributesTimerEntity.setNum(20);
kieSession.insert(attributesTimerEntity);
kieSession.fireUntilHalt();
Thread.sleep(10000);
kieSession.halt();
kieSession.dispose();
}
}
我们看到,规则在周期性触发。
注意:如果规则中有用到了timer属性,匹配规则需要调用kieSession.fireUntilHalt();这里涉及一个规则引擎的执行模式和线程问题,关于具体细节,我们后续讨论。
date-effective属性用于指定规则的生效时间,即只有当前系统时间大于等于设置的时间或者日期规则才有可能触发。默认日期格式为:dd-MMM-yyyy。用户也可以自定义日期格式。
在/resources/rules下创建规则文件attributes-date-effective.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesDateEffectiveEntity
/*
用于测试Drools 属性: date-effective
*/
rule "rule_attributes_date_effective"
// date-effective "20-七月-2020"
date-effective "2024-01-15"
when
$attributesDateEffectiveEntity:AttributesDateEffectiveEntity(num > 1)
then
System.out.println("规则 rule_attributes_date_effective 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/18 20:20:31
* @description data-effective属性实体
*/
@Data
public class AttributesDateEffectiveEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesDateEffectiveEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/18 20:22:13
* @description date-effective 属性测试类
*/
public class AttributesDateEffectiveTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test() {
KieSession kieSession = kieBase.newKieSession();
AttributesDateEffectiveEntity attributesDateEffectiveEntity = new AttributesDateEffectiveEntity();
attributesDateEffectiveEntity.setNum(20);
kieSession.insert(attributesDateEffectiveEntity);
kieSession.fireAllRules();
kieSession.dispose();
}
}
我们设置的时间,小于当前时间,所以触发了。我们可以设置一下大于当前时间的值,再看下测试结果。
从测试结果中我们发现,当我设置时间值为“2024-01-20”,值大于当前时间,所以就没触发。
注意:执行测试时,需要在VM参数上加上日期格式:-Ddrools.dateformat=yyyy-MM-dd,不然执行测试用例会报错。在生产环境所在规则引擎的JVM设置中,也需要设置此参数,以保证开发和生产的一致性。
date-expires属性用于指定规则的失效时间,即只有当前系统时间小于设置的时间或者日期规则才有可能触发。默认日期格式为:dd-MMM-yyyy。用户也可以自定义日期格式。
在/resources/rules下创建规则文件attributes-date-expires.drl,文件内容如下:
package rules
import com.ningzhaosheng.drools.entity.AttributesDateExpiresEntity
/*
用于测试Drools 属性: date-expires
*/
rule "rule_attributes_date_expires"
date-expires "2024-01-15"
when
$attributesDateExpiresEntity:AttributesDateExpiresEntity(num > 1)
then
System.out.println("规则 rule_attributes_date_expires 触发");
end
package com.ningzhaosheng.drools.entity;
import lombok.Data;
/**
* @author ningzhaosheng
* @date 2024/1/18 20:57:49
* @description date-expires 属性实体
*/
@Data
public class AttributesDateExpiresEntity {
private Integer num;
}
package com.ningzhaosheng.drools.client;
import com.ningzhaosheng.drools.DroolsApplicationTests;
import com.ningzhaosheng.drools.entity.AttributesDateExpiresEntity;
import org.junit.jupiter.api.Test;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import javax.annotation.Resource;
/**
* @author ningzhaosheng
* @date 2024/1/18 20:56:12
* @description date-expires 属性测试类
*/
public class AttributesDateExpiresTest extends DroolsApplicationTests {
@Resource
public KieBase kieBase;
@Test
public void test(){
KieSession kieSession = kieBase.newKieSession();
AttributesDateExpiresEntity attributesDateExpiresEntity = new AttributesDateExpiresEntity();
attributesDateExpiresEntity.setNum(20);
kieSession.insert(attributesDateExpiresEntity);
kieSession.fireAllRules();
kieSession.dispose();
}
}
当我设置的时间,小于当前系统时间时,发现规则并没有触发。
注意:需要在VM参数上加上日期格式:-Ddrools.dateformat=yyyy-MM-dd,不然执行测试用例会报错。在生产环境所在规则引擎的JVM设置中,也需要设置此参数,以保证开发和生产的一致性。
好了,本次分享就到这里,欢迎大家继续阅读《Drools》专栏内容,如果有帮助到大家,欢迎大家点赞+关注+收藏,有疑问也欢迎大家评论留言!