第2-4-4章 规则引擎Drools规则属性-业务规则管理系统-组件化-中台
5. 规则属性
前面我们已经知道了规则体的构成如下:
rule "ruleName"
attributes
when
LHS
then
RHS
end
本章节就是针对规则体的attributes属性部分进行讲解。Drools中提供的属性如下表(部分属性):
属性名 | 说明 |
---|---|
salience | 指定规则执行优先级 |
dialect | 指定规则使用的语言类型,取值为java和mvel |
enabled | 指定规则是否启用 |
date-effective | 指定规则生效时间 |
date-expires | 指定规则失效时间 |
activation-group | 激活分组,具有相同分组名称的规则只能有一个规则触发 |
agenda-group | 议程分组,只有获取焦点的组中的规则才有可能触发 |
timer | 定时器,指定规则触发的时间 |
auto-focus | 自动获取焦点,一般结合agenda-group一起使用 |
no-loop | 防止死循环 |
5.1 enabled属性
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
5.2 dialect属性
dialect属性用于指定当前规则使用的语言类型,取值为java和mvel,默认值为java。
注:mvel是一种基于java语法的表达式语言。
mvel像正则表达式一样,有直接支持集合、数组和字符串匹配的操作符。
mvel还提供了用来配置和构造字符串的模板语言。
mvel表达式内容包括属性表达式,布尔表达式,方法调用,变量赋值,函数定义等。
5.3 salience属性
salience属性用于指定规则的执行优先级,取值类型为Integer。数值越大越优先执行。每个规则都有一个默认的执行顺序,如果不设置salience属性,规则体的执行顺序为由上到下。
可以通过创建规则文件salience.drl来测试salience属性,内容如下:
package test.salience
rule "rule_1"
when
eval(true)
then
System.out.println("规则rule_1触发");
end
rule "rule_2"
when
eval(true)
then
System.out.println("规则rule_2触发");
end
rule "rule_3"
when
eval(true)
then
System.out.println("规则rule_3触发");
end
通过控制台可以看到,由于以上三个规则没有设置salience属性,所以执行的顺序是按照规则文件中规则的顺序由上到下执行的。接下来我们修改一下文件内容:
package testsalience
rule "rule_1"
salience 9
when
eval(true)
then
System.out.println("规则rule_1触发");
end
rule "rule_2"
salience 10
when
eval(true)
then
System.out.println("规则rule_2触发");
end
rule "rule_3"
salience 8
when
eval(true)
then
System.out.println("规则rule_3触发");
end
通过控制台可以看到,规则文件执行的顺序是按照我们设置的salience值由大到小顺序执行的。
建议在编写规则时使用salience属性明确指定执行优先级。
5.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"
when
// no-loop true
$student:Student(age == 25)
then
update($student);//注意此处执行update会导致当前规则重新被激活
System.out.println("规则rule_noloop触发");
end
第二步:编写单元测试
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
Student student = new Student();
student.setAge(25);
//将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配,如果规则匹配成功则执行规则
kieSession.insert(student);
kieSession.fireAllRules();
kieSession.dispose();
通过控制台可以看到,由于我们没有设置no-loop属性的值,所以发生了死循环。接下来设置no-loop的值为true再次测试则不会发生死循环。
5.5 activation-group属性
activation-group属性是指激活分组,取值为String类型。具有相同分组名称的规则只能有一个规则被触发。
第一步:编写规则文件/resources/rules/activationgroup.drl
package testactivationgroup
/*
此规则文件用于测试activation-group属性
*/
rule "rule_activationgroup_1"
activation-group "mygroup"
when
then
System.out.println("规则rule_activationgroup_1触发");
end
rule "rule_activationgroup_2"
activation-group "mygroup"
when
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属性确定。
5.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
第二步:编写单元测试
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
//设置焦点,对应agenda-group分组中的规则才可能被触发
kieSession.getAgenda().getAgendaGroup("myagendagroup_1").setFocus();
kieSession.fireAllRules();
kieSession.dispose();
通过控制台可以看到,只有获取焦点的分组中的规则才会触发。与activation-group不同的是,activation-group定义的分组中只能够有一个规则可以被触发,而agenda-group分组中的多个规则都可以被触发。
5.7 auto-focus属性
auto-focus属性为自动获取焦点,取值类型为Boolean,默认值为false。一般结合agenda-group属性使用,当一个议程分组未获取焦点时,可以设置auto-focus属性来控制。
第一步:修改/resources/rules/agendagroup.drl文件内容如下
package testagendagroup
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"
auto-focus true //自动获取焦点
when
then
System.out.println("规则rule_agendagroup_3触发");
end
rule "rule_agendagroup_4"
agenda-group "myagendagroup_2"
auto-focus true //自动获取焦点
when
then
System.out.println("规则rule_agendagroup_4触发");
end
第二步:编写单元测试
KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();
kieSession.fireAllRules();
kieSession.dispose();
通过控制台可以看到,设置auto-focus属性为true的规则都触发了。
5.8 timer属性
timer属性可以通过定时器的方式指定规则执行的时间,使用方式有两种:
方式一:timer (int: <initial delay> <repeat interval>?)
此种方式遵循java.util.Timer对象的使用方式,第一个参数表示几秒后执行,第二个参数表示每隔几秒执行一次,第二个参数为可选。
方式二: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进行定时执行,需要程序能够持续一段时间才能够看到定时器触发的效果。
5.9 date-effective属性
date-effective属性用于指定规则的生效时间,即只有当前系统时间大于等于设置的时间或者日期规则才有可能触发。默认日期格式为:dd-MMM-yyyy。用户也可以自定义日期格式。
第一步:编写规则文件/resources/rules/dateeffective.drl
package testdateeffective
/*
此规则文件用于测试date-effective属性
*/
rule "rule_dateeffective_1"
date-effective "2022-11-13 11:36:49"
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();
注意:上面的代码需要设置日期格式,否则我们在规则文件中写的日期格式和默认的日期格式不匹配程序会报错。
5.10 date-expires属性
date-expires属性用于指定规则的失效时间,即只有当前系统时间小于设置的时间或者日期规则才有可能触发。默认日期格式为:dd-MMM-yyyy。用户也可以自定义日期格式。
第一步:编写规则文件/resource/rules/dateexpires.drl
package testdateexpires
/*
此规则文件用于测试date-expires属性
*/
rule "rule_dateexpires_1"
date-expires "2023-11-13 11:41:40"
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();
注意:上面的代码需要设置日期格式,否则我们在规则文件中写的日期格式和默认的日期格式不匹配程序会报错。
第2-4-4章 规则引擎Drools规则属性-业务规则管理系统-组件化-中台的更多相关文章
- 小明历险记:规则引擎drools教程一
小明是一家互联网公司的软件工程师,他们公司为了吸引新用户经常会搞活动,小明常常为了做活动加班加点很烦躁,这不今天呀又来了一个活动需求,我们大家一起帮他看看. 小明的烦恼 活动规则是根据用户购买订单的金 ...
- [Drools]JAVA规则引擎 -- Drools 2
上一篇文章 http://blog.csdn.net/quzishen/archive/2011/01/25/6163012.aspx 描述了一些常用的drools的语法标签和一个模拟实例即发送积分的 ...
- [Drools]JAVA规则引擎 -- Drools
Drools是一个基于Java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...
- Java规则引擎drools:drt动态生成规则并附上具体项目逻辑
一 整合 由于本人的码云太多太乱了,于是决定一个一个的整合到一个springboot项目里面. 附上自己的项目地址https://github.com/247292980/spring-boot 以整 ...
- 开源规则引擎 drools
java语言开发的开源业务规则引擎 DROOLS(JBOSS RULES )具有一个易于访问企业策略.易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快.效率高.业务分析师或审核人员可以利用 ...
- 规则引擎drools封装
一.前言 网上规则引擎drools介绍很多,并且有很多细致的说明,作者也不敢托大说自己的好用,但作者经过2个项目使用过规则引擎后,自己对规则引擎的理解并进行封装,对规则内容及如何使用,有自己的一番实践 ...
- 开源规则引擎 Drools 学习笔记 之 -- 1 cannot be cast to org.drools.compiler.kie.builder.impl.InternalKieModule
直接进入正题 我们在使用开源规则引擎 Drools 的时候, 启动的时候可能会抛出如下异常: Caused by: java.lang.ClassCastException: cn.com.cheng ...
- 使用规则引擎Drools计算圆周率PI
实际上是使用规则引擎能够更新工作内存区重新匹配规则实现迭代功能. 使用了策略模式实现. <规则引擎与RETE算法介绍> PPT : http://files.cnblogs.com/lov ...
- JAVA规则引擎 -- Drools
Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...
- 规则引擎 drools
https://www.jianshu.com/p/725811f420db 深入了解Drools 简单介绍 笔者正在做风控系统,风控系统里边存在非常多的规则(比如:age < 16 || ag ...
随机推荐
- 【java8新特性】01:函数式编程及Lambda入门
我们首先需要先了解什么是函数式编程.函数式编程是一种结构化编程范式.类似于数学函数.它关注的重点在于数据操作.或者说它所提倡的思想是做什么,而不是如何去做. 自Jdk8中开始.它也支持函数式编程.函数 ...
- P1829 [国家集训队]Crash的数字表格
P1829 [国家集训队]Crash的数字表格 原题传送门 前置芝士 莫比乌斯反演 乘法逆元 数论分块 正文 //补充:以下式子中的除法均为整除 由题目可以得知,这道题让我们所求的数,用一个式子来表达 ...
- 案例分享 生产环境逐步迁移至k8s集群 - pod注册到consul
#案例分享 生产环境逐步迁移至k8s集群 - pod注册到consul #项目背景 多套业务系统, 所有节点注册到consul集群,方便统一管理 使用consul的dns功能, 所有节点hostnam ...
- vue中修改滚动条样式
这是一个在VUE中的设置滚动条样式的方法,该方法只适用于Chrome浏览器,亲测在火狐不适用 样式写在 APP.vue 中,可以用在全局,如果只用在那个盒子中,只需要在::前面加上盒子的class名就 ...
- 我的 Kafka 旅程 - 性能调优
Producer 于 config/producer.properties 配置文件中的项 # 序列化数据压缩方式 [none/gzip/snappy/lz4/zstd] compression.ty ...
- js动态获取当前时间(年、月、日、上午/下午、时、分、秒)
//获取动态时间function mytime() { var mydate = new Date(); var year = mydate.getFullYear(); var month = my ...
- 【Java】 DirectByteBuffer堆外内存回收
PhantomReference虚引用 在分析堆外内存回收之前,先了解下PhantomReference虚引用. PhantomReference需要与ReferenceQueue引用队列结合使用,在 ...
- VM运行centos网络配置(出现错误)详解
一般按照正常安装流程到这一步的时候可以直接点击网络和主机名,但是我这里并没有连接成功,因此我跳过了这里想着后面再配置 后面通过ping www.baidu.com以及ping 百度的ip地址(如何获得 ...
- java.lang.ClassNotFoundException: Cannot find class: “com.mysql.jdbc.Driver“的报错问题
@Testpublic void testConnectionTest5() throws Exception { //1.读取配置文件,获取4个基本信息 InputStream is = Conne ...
- 2.RabbitMQ系列之生产者
1. 新建队列 2. 新增POM.xml配置文件 <parent> <groupId>org.springframework.boot</groupId> < ...