文章目录
-
- 1.DRL文件的组成:
- 2.package
- 3.import
- 4.function
- 5.query
- 6.declare
- 7.global
- 8.rule
-
- 8.1.规则属性
- 8.2.LHS
-
- 8.2.1.语法格式
- 8.2.2.运算符优先级
- 8.2.3.特殊的运算符
-
- [1.`matches`, `not matches`](#1.
matches
,not matches
) - [2.`contains`, `not contains`](#2.
contains
,not contains
) - [3.`memberOf`, `not memberOf`](#3.
memberOf
,not memberOf
) - [4.`in`, `notin`](#4.
in
,notin
) - 5.`soundslike`
- 6.`str`
- 7.`from`
- [1.`matches`, `not matches`](#1.
- 8.3.RHS
1.DRL文件的组成:
java
package
import
function // Optional
query // Optional
declare // Optional
global // Optional
rule "rule name"
// Attributes
when
// Conditions
then
// Actions
end
rule "rule2 name"
...
以上内容,只是梳理了DRL文件中组成的元素及其顺序(顺序非强制性要求,这是这样便于内容阅读)。
2.package
类似于 Java
中的 package
,声明规则的唯一命名空间(包)。包必须有一个名称空间,并使用包名称的标准 Java
约定进行声明;即没有空格,这与允许空格的规则名称不同。根据元素的顺序,它们可以以任何顺序出现在规则文件中,但package
语句除外,它必须位于文件的顶部。在任何情况下,分号都是可选的。
任何规则属性(见"规则属性"一节)也可以在包级别编写,取代该属性的默认值。修改后的默认值仍可能被规则中的属性设置所替换。
示例
java
// 带分号
package com.test;
// 不带分号
package com.test
3.import
类似于 Java
中的 import
。DRL文件中在规则中需要导入使用的对象的完全限定路径和类型名称。Drools引擎自动从与DRL包同名的Java
包和Java.lang
包中导入类。
示例
java
// 不需要导入,已自动导入
// import java.lang.String;
import com.a.b.DroolsObject;
4.function
类似于 Java
中的 method
。可以将重复代码或者逻辑性代码封装成一个函数,或者将工具/辅助类中的静态方法导入为函数,然后在规则LHS/RHS部分中按名称使用该函数。
示例
java
// 导入静态方法/函数
import static org.example.applicant.MyFunctions.hello;
// 函数1
function boolean ageJudge(Integer i){
if (i > 10){
return true;
} else {
return false;
}
}
// 使用函数
rule "age"
enabled true
when
eval(ageJudge(10));
then
end
5.query
查询在工作内存中相关的事实对象。查询的名称对于 KieBase
是全局的,因此对于该项目中的所有其他规则的查询必须是唯一的。ksession.getQueryResults("name")
获取查询结果,其中"name"是查询名称。
示例
java
package drools.drl
// 导入输入类型
import com.ahao.project.input.UserIn;
global com.ahao.project.output.UserOut output;
query "age>10"
$in:UserIn(age > 10)
end
获取结果
java
QueryResults queryResults = kieSession.getQueryResults("age>10");
Iterator<QueryResultsRow> iterator = queryResults.iterator();
while (iterator.hasNext()) {
QueryResultsRow next = iterator.next();
log.info("查询结果:{}",next.get("$in"));
}
// [main] INFO DroolsTest2 - 查询结果:UserIn(age=35)
// [main] INFO DroolsTest2 - 查询结果:UserIn(age=45)
6.declare
声明类型。用于在DRL声明一个新的类型。
示例
java
package drools.drl
import com.ahao.project.input.UserIn
// 声明一个Person类型
declare Person
name:String
age:Integer
end
rule "age"
enabled true
when
$in:UserIn(age > 10)
then
Person person = new Person();
person.setAge($in.getAge());
person.setName("命中规则");
System.out.println(person);
end
结果
7.global
全局变量。DRL文件中的全局变量通常为规则提供数据或服务,如在then中使用的应用程序服务(service),并从规则返回数据。
示例
java
// 全局变量的定义
global com.ahao.project.output.UserOut output;
// 可以有多个
// global com.ahao.project.output.UserOut output222;
注意:
执行规则时,需要先设置全局变量对象
javakieSession.setGlobal("output", output); // 然后再 kieSession.fireAllRules()
8.rule
rule语法结构如下图
8.1.规则属性
属性 | 默认值 | 描述 |
---|---|---|
salience |
0 | 规则优先级。在同一个 activation-group 中,具有较高优先级(值越大)的规则优先执行 示例: salience 10 |
enabled |
true | 是否启用该规则 示例: enabled true |
date-effective |
null | 只有当前日期时间在 date-effective 属性之后 时,才能激活该规则 示例: date-effective "4-Sep-2018" |
date-expires |
null | 只有当前日期时间在 date-expires 属性之前 时,才能激活该规则 示例: date-expires "4-Oct-2018" |
no-loop |
false | 是否可循环。某些情况下(update函数等),规则可以被再次激活 示例: no-loop true |
agenda-group |
default | 议程组。对议程进行分区,以提供对规则组的更多执行控制。只有获得焦点的议程组中的规则才能被激活。 示例: agenda-group "GroupName" |
activation-group |
null | 激活组。一个激活组只能激活一个规则,即使其他规则体的LHS部分仍然为true也不会再被执行。 示例: activation-group "GroupName" |
duration |
null | 以毫秒为单位的持续时间。如果规则条件当前满足,则在该持续时间之后可以激活规则。 示例: duration 10000 |
timer |
null | 调度器。"时间间隔"或"cron"计时器定义 示例: timer ( cron:* 0/15 * * * ? ) (every 15 minutes) |
calendar |
null | 用于调度规则的 Quartz calendar 示例: calendars "* * 0-7,18-23 ? * *" (exclude non-business hours) |
auto-focus |
false | 自动获取焦点,仅适用于议程组内的规则。选择该选项后,下次激活规则时,会自动将焦点指定给规则所分配的议程组: 示例:auto-focus true |
lock-on-active |
false | 仅适用于规则流组或议程组内的规则。选择该选项后,下次规则的规则流组变为活动状态或规则的议程组收到焦点时,在规则流组不再活动或议程组失去焦点之前,无法再次激活规则。是no-loop属性的更强版本。 示例: lock-on-active true |
ruleflow-group |
null | 规则流组。只有被关联的规则流激活这个组时,规则才能激活 示例: ruleflow-group "GroupName" |
dialect |
mvel | 用来定义规则中要使用的语言类型 示例: dialect "java" |
8.2.LHS
规则的when部分(也称为Left Hand Side(LHS))包含执行操作必须满足的条件。
8.2.1.语法格式
格式
java
// 格式如下(对象名称前的 $ 非必需的)
when
$对象名称:事实对象的全限定类名(字段约束)
// 如果已经import了事实对象的全限定类名
when
$对象名称:事实对象的类名(字段约束)
示例
java
// 示例1
when
$p:com.test.Person(age > 10 || name == "jack")
// 示例2
import com.test.Person;
when
p:Person(age > 10 || name == "jack")
8.2.2.运算符优先级
操作类型 | 符号 | Notes |
---|---|---|
嵌套或(null-safe)属性访问 | . , .() , !. |
不是标准的Java语义 |
List 或者 Map 访问 |
[] |
不是标准的Java语义 |
约束绑定(类型绑定) | : |
不是标准的Java语义 |
乘积 | * , / ,% |
|
加减 | + , - |
|
位运算 | >> , >>> , << |
|
关系型 | < , <= , > , >= , instanceof |
|
等于 | == != |
使用equals() 和!equals() 语义,非标准Java same 和not same 语义 |
非短路 AND |
& |
|
非短路异运算 | ^ |
|
非短路包含 OR |
` | ` |
逻辑运算 AND |
&& |
|
逻辑运算 OR |
` | |
三元运算符 | ? : |
|
逗号分隔 AND |
, |
不是标准的Java语义 |
运算符
==
使用null-safe equals()
语义,而不是通常的equals
语义。例如,Person(firstName=="John")
类似于java.util。Objects.equals(person.getFirstName(),"John")
,并且由于"John"
不为null
,所以该模式也类似于"John".equals(person.get-FirstName)
。
以上运算符都基本上类似java中的运算符。接下会介绍一些特殊的运算符。
8.2.3.特殊的运算符
1.matches
, not matches
判断与指定的Java正则表达式匹配或不匹配。
示例
java
Person( country matches "(USA)?\\S*UK" )
2.contains
, not contains
数组或集合字段是否包含指定值。可以使用这些运算符来代替String.contains()和!String.contents()。
示例
java
// 姓名包含王
Person( name contains "王" )
// 假设一个人有多个手机号,phones:List<String>
// 手机号不包含12345678901
Person( phones not contains "12345678901" )
3.memberOf
, not memberOf
是否为数组或集合的成员。
示例
java
// 手机号不包含12345678901
Person( "12345678901" not memberOf phones)
4.in
, notin
指定约束中要匹配的多个可能值(复合值限制)。
示例
java
// 名称为 jack 或者 mary
Person( name in ("jack","mary"))
5.soundslike
验证单词是否具有与给定值几乎相同的发音(英语发音)。
示例
java
// firstName "Jon" or "John":
Person( firstName soundslike "John" )
6.str
验证字符串字段是以指定值开始,以指定值结束,或者字符串的长度。
示例
java
// 消息的以"R1"开始
Message( msg str[startsWith] "R1" )
// 消息的以"R2"结尾
Message( msg str[endsWith] "R2" )
// 消息的长度为17
Message( msg str[length] 17 )
7.from
获取数据源。
示例
java
// 从模式绑定(变量)中获取数据源
rule "rule1"
when
Person( $personAddress : address )
Address( zipcode == "11110" ) from $personAddress
then
end
// 从图形符号中获取数据源
rule "rule1"
when
$p : Person()
$a : Address( zipcode == "23920W" ) from $p.address
then
end
// 从迭代器中获取数据源
rule "rule1"
when
$order : Order()
$item : OrderItem( value > 100 ) from $order.items
then
end
8.3.RHS
规则的then部分(也称为 Right Hand Side(RHS))。当满足规则的when部分时要执行的操作。操作的主要目的是在Drools引擎的工作内存中插入、删除或修改数据。有效的规则操作是小的、声明性的和可读的。如果需要在规则操作中使用命令式或条件式代码,请将规则划分为多个更小、更具声明性的规则。
8.3.1.set
赋值。
示例
java
$person.setName("jack");
8.3.2.modify
针对某个事实进行修改,并将更改通知Drools引擎。
语法
java
modify ( <fact-expression> ) {
<expression>,
<expression>,
...
}
示例
java
modify( Person ) {
setAge( 100 ),
setName ( "nick" )
}
8.3.3.update
指定要更新的字段和整个相关事实,并将更改通知Drools引擎。
语法
java
update ( <object, <handle> )
update ( <object> )
示例
java
person.setAge( 100 );
update( person );
8.3.4.insert
将一个新的事实插入Drools引擎的工作内存中。
语法
java
insert( new <object> );
示例
java
insert( new Person() );
8.3.5.delete
从Drools引擎中删除对象。
语法
java
delete( <object> );
示例
java
delete( person );
8.3.6.drools.halt()
终止规则执行。
示例
java
rule "end_rule"
enabled true
when
then
drools.halt();
end