文章目录
- drl文件构成-rule部分
- 条件部分 LHS
- 模式(Pattern)、绑定变量
- 属性约束
- DRL中支持的规则条件元素(关键字)
- 运算符
- 比较操作符
- 条件元素继承
- 条件元素do对应多then条件
drl文件构成-rule部分
drl文件构成,位于官网的第5章位置,也是drools作为规则引擎应用的最核心部分。
其中rule模块,包括属性(Attribute - rule)、条件(Condition - when)、结果(Action - then)是5.1.7、5.1.8、5.1.9 三小节部分内容。
- Rule Language Reference
官网链接:https://docs.drools.org/7.73.0.Final/drools-docs/html_single/index.html#_droolslanguagereferencechapter
条件部分 LHS
when和then中间的部分为条件部分,可以为空,为空时,相当于 eval( true )
模式(Pattern)、绑定变量
模式(pattern) 也叫类型约束
举例:
Person( age == 50 )
// This is the same as the following getter format:
Person( getAge() == 50 )
Person是我们定义的一个实体对象,如果在条件中出现了类似这样的实体对象,说明该条件匹配的前提条件是session内存中存在Person类型的对象,且属性age == 50. 类似Person 这样的实体对象, 在drools中叫做 Fact。
即代码中要这样才能触发该规则:
Person person = new Person();
person.setAge(50);
kieSession.insert(person);
绑定变量:将模式赋值给变量,可以把整个fact对象赋值变量,也可以将某个属性赋值变量,$变量名: fact对象,或 $变量名:属性,示例如下:
// 整个person对象赋值给 $p,之后这个$p可以直接使用
rule "simple rule"
when
$p : Person()
then
System.out.println( "Person " + $p );
end
// age属性赋值给变量,这个规则需要两个person实例
rule "simple rule 1"
when
// Two persons of the same age:
Person( $firstAge : age ) // Binding
Person( age == $firstAge ) // Constraint expression
then
System.out.println( "firstAge " + $firstAge );
end
更多模式及绑定变量使用方式官网有非常明确的说明,这里列举几个:
// Do not use the following format:
Person( $a : age * 2 < 100 )
// Use the following format instead:
Person( age * 2 < 100, $a : age )
Person( $a : (age * 2) )
// Example pattern to access multiple properties
Person( name == "mark", address.city == "london", address.country == "uk" )
// Example pattern with grouped constraints
Person( name == "mark", address.( city == "london", country == "uk") )
// Example patterns with inline casting to a subtype
// Inline casting with subtype name:
Person( name == "mark", address#LongAddress.country == "uk" )
// Inline casting with fully qualified class name:
Person( name == "mark", address#org.domain.LongAddress.country == "uk" )
// Multiple inline casts:
Person( name == "mark", address#LongAddress.country#DetailedCountry.population > 10000000 )
// 判断类型
Person( name == "mark", address instanceof LongAddress, address.country == "uk" )
属性约束
DRL中支持的规则条件元素(关键字)
DRL中支持的规则条件元素(关键字)
这部分在初接触drools的时候几乎不用。最常用的是and /or/exists。另外eval,当无条件时,相当于 eval(true).
这部分描述的是条件与条件直接的关系,也就是pattern与pattern之间的关系。
其他的作者目前没有示例进行讲解,由于时间关系暂时略过,若后续有时间详细做示例后回来补充。可直接官网查看,内容位于5.1.8.8.
运算符
运算符这小节内容很少,也是我自己总结的单独列出来了,是规则条件或结果中的属性的运算符,与java相似。
比较操作符
- </>/=/!=/&&/||等 这些与java比较操作符一样。
- 字符串比较
matches, not matches,匹配的是正则表达式
str[startsWith],str[endsWith],str[length],是以…开头、以…结尾、字符串长度的比较。
以…开头/以…结尾使用 matces可以实现。 - 集合比较
contains , not contains:也可以比较字符串是否包含(字符串是字符的集合)
memberof, not memberof:后跟的集合内容必须是一个变量,即需要先将要比较的内容赋值给某个$开头的变量。
in, notin:第二个操作数必须是一个逗号分隔的值列表,用括号括起来。
附一个官网的比较操作符运算优先级
条件元素继承
rule "Give 10% discount to customers older than 60"
when
$customer : Customer( age > 60 )
then
modify($customer) { setDiscount( 0.1 ) };
end
rule "Give free parking to customers older than 60"
when
$customer : Customer( age > 60 )
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
end
使用继承,则以上以上两个规则这样写,适合条件较多的继承方式:
rule "Give 10% discount to customers older than 60"
when
$customer : Customer( age > 60 )
then
modify($customer) { setDiscount( 0.1 ) };
end
rule "Give free parking to customers older than 60"
extends "Give 10% discount to customers older than 60"
when
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
end
条件元素do对应多then条件
这部分既是条件部分内容也涉及结果部分,当条件部分满足 1 时,对应结果处理,满足2时对应结果处理不同等。即一个规则,可能有多种处理结果。
官网示例如下(该例子,是以上两个规则的合并版):
即,当满足客户年龄 > 60时,setDiscount( 0.1 ),
满足 客户年龄 > 60 且 车的所有者是该客户时,setFreeParking( true )
rule "Give 10% discount and free parking to customers older than 60"
when
$customer : Customer( age > 60 )
do[giveDiscount]
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
then[giveDiscount]
modify($customer) { setDiscount( 0.1 ) };
end
升级版:
rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones"
when
$customer : Customer( age > 60 )
if ( type == "Golden" ) do[giveDiscount10]
else if ( type == "Silver" ) break[giveDiscount5]
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
then[giveDiscount10]
modify($customer) { setDiscount( 0.1 ) };
then[giveDiscount5]
modify($customer) { setDiscount( 0.05 ) };
end
此示例规则为60岁以上的Golden客户提供10%的折扣和免费停车,但为Silver客户提供5%的折扣而不提供免费停车。
该规则使用关键字break而不是do激活名为giveDiscount5的结果。
关键字do在Drools引擎议程中安排一个结果,使规则条件的剩余部分能够继续求值,而break则阻止任何进一步的条件求值。
如果一个命名的结果与任何带有do的条件都不对应,而是用break激活,则规则将无法编译,因为永远无法达到规则的条件部分。