DRL中的规则条件(WHEN,LHS)
规则结构
规则中的条件
DRL中的when部分就是规则的条件(通常又叫做规则的左手边,即:Left Hand Side(LHS))
只有满足了所有的条件,才回去执行then部分,如果when部分为空,就是没有条件,那么就默认为true,下面是一个空条件的例子:
rule "Always insert applicant"
when
// Empty
then // Actions to be executed once
insert( new Applicant() );
end
// 规则在引擎内部会变成如下这样:
rule "Always insert applicant"
when
eval( true )
then
insert( new Applicant() );
end
如果条件之间没有连词的话(如:and,or,not),默认的就是and,就是同时满足所有条件
rule "Underage"
when
application : LoanApplication()
Applicant( age < 21 )
then
// Actions
end
// 在规则引擎内部是下面这样,加上个and:
rule "Underage"
when
application : LoanApplication()
and Applicant( age < 21 )
then
// Actions
end
模式和约束
在规则的条件中定义模式并由规则去匹配,一个模式可以匹配每一个被插入到working memory中的fact,同时模式也可以增加约束去限制哪些fact会被匹配上
举个没有约束的例子,下面定的这个模式,可以匹配所有插入到WM中的Person对象。
Person()
这个类型不需要是一个真是的class,可以是父类甚至是接口,比如下面这个例子就会匹配WM中所有的对象
Object() // Matches all objects in the working memory
增加了约束的模式,限制了age等于50
Person( age == 50 )
约束是一个会返回true或false的表达式,和java很像,但是有所增强,可以直接通过属性名访问属性
Person( age == 50 )
// 这两者是一样的
Person( getAge() == 50 )
如果约束的值类型和属性的类型不一致,那么drools内部会自动做强制类型转换,如果转不了就会报错,比如:
Person( age == "10" ) // "10" 强制转为 10
多个约束:
// Person is at least 50 years old and weighs at least 80 kilograms:
Person( age > 50, weight > 80 )
// Person is at least 50 years old, weighs at least 80 kilograms, and is taller than 2 meters:
Person( age > 50, weight > 80, height > 2 )
也可以使用&&和||,但是不可以和","混用
// 不能用:
Person( ( age > 50, weight > 80 ) || height > 2 )
// 应该这样用:
Person( ( age > 50 && weight > 80 ) || height > 2 )
在模式和约束中绑定变量
使用*$变量名*这种形式来绑定变量:
rule "simple rule"
when
$p : Person()
then
System.out.println( "Person " $p );
end
注意:
// 不能这样用:
Person( $age : age * 2 < 100 )
// 要这样用:
Person( age * 2 < 100, $age : age )
嵌套约束和内联强制转换
嵌套约束的使用:
Person( name == "mark", address.city == "london", address.country == "uk" )
//或者写成:
Person( name == "mark", address.( city == "london", country == "uk") )
内联强制转换:
// 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 )
使用instanceof进行类型判断
Person( name == "mark", address instanceof LongAddress, address.country == "uk" )
日期约束
默认的日期格式是dd-mm-yyyy,你也可以自定义格式通过系统属性drools.dateformat=“dd-mm-yyyy hh:mm”
Person( bornBefore < "27-Oct-2009" )
DRL特有的操作符
DRL支持标准的java语法,但是有些操作符是DRL所独有的,比如:.(),#,通过前者去分组获取属性值,通过后者强制类型转换成子类型
// Ungrouped property accessors:
Person( name == "mark", address.city == "london", address.country == "uk" )
// Grouped property accessors:
Person( name == "mark", address.( city == "london", country == "uk") )
// 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 )
!. 操作符相当于!=null
Person( $streetName : address!.street )
// This is internally rewritten in the following way:
Person( address != null, $streetName : address.street )
[ ] 获取list或map的值
// The following format is the same as `childList(0).getAge() == 18`:
Person(childList[0].age == 18)
// The following format is the same as `credentialMap.get("jdoe").isValid()`:
Person(credentialMap["jdoe"].valid)
matches , not matches 正则匹配,与java中使用正则表达式相同
Person( country matches "(USA)?\\S*UK" )
Person( country not matches "(USA)?\\S*UK" )
contains , not contains 判断值是否在Array或Collection中
// Collection with a specified field:
FamilyTree( countries contains "UK" )
FamilyTree( countries not contains "UK" )
// Collection with a variable:
FamilyTree( countries contains $var )
FamilyTree( countries not contains $var )
同样可以用于字符串的包含,相当于String.contains(),!String.contains()
// Sting literal with a specified field:
Person( fullName contains "Jr" )
Person( fullName not contains "Jr" )
// String literal with a variable:
Person( fullName contains $var )
Person( fullName not contains $var )
memberOf , not memberOf 判断字段值是否在Array或Collection中,它们必须是 变量
FamilyTree( person memberOf $europeanDescendants )
FamilyTree( person not memberOf $europeanDescendants )
soundslike 英语发音相似,使用 Soundex algorithm算法判断(nubility)
// Match firstName "Jon" or "John":
Person( firstName soundslike "John" )
str 判断一个字符串是否已指定值开头、结尾、以及长度是多少
// Verify what the String starts with:
Message( routingValue str[startsWith] "R1" )
// Verify what the String ends with:
Message( routingValue str[endsWith] "R2" )
// Verify the length of the String:
Message( routingValue str[length] 17 )
in , not in
Person( $color : favoriteColor )
Color( type in ( "red", "blue", $color ) )
Person( $color : favoriteColor )
Color( type notin ( "red", "blue", $color ) )
还有很多其他的操作符合关键字可以参考这个
DRL中的规则行为(THEN)
DRL中的then部分就是规则触发后的行为(规则的右手边Right Hand Side (RHS) ),基本上可以概况为向working memory中 insert、delete、或modify数据。
rule "Underage"
when
application : LoanApplication()
Applicant( age < 21 )
then
application.setApproved( false );
application.setExplanation( "Underage" );
end
DRL中支持的行为
set 设置字段值,和java相同
set<field> ( <value> )
例:
$application.setApproved ( false );
$application.setExplanation( "has been bankrupt" );
modify 修改对象并告知engine
modify ( <fact-expression> ) {
<expression>,
<expression>,
...
}
例:
modify( LoanApplication ) {
setAmount( 100 ),
setApproved ( true )
}
update 更新对象并告知engine
update ( <object, <handle> ) // Informs the Drools engine that an object has changed
update ( <object> ) // Causes `KieSession` to search for a fact handle of the object
例:
LoanApplication.setAmount( 100 );
update( LoanApplication );
可以看出,我们可以用modify来代替,但是update提供了额外的监听器,来监听属性值的变化,属性监听器
insert 插入一个新的fact
//用法:
insert( new <object> );
//例:
insert( new Applicant() );
insertLogical 逻辑插入一个新的fact,drools engine负责这个fact的创建和回收,当创建这个fact的条件为false时,这个fact就会被engine自动回收掉
//用法:
insertLogical( new <object> );
//例:
insertLogical( new Applicant() );
delete 删除一个对象,retract也可以,但是建议使用delete
//用法
delete( <object> );
//例:
delete( Applicant );
注释
和java中的注释相同
rule "Underage"
// This is a single-line comment.
when
$application : LoanApplication() // This is an in-line comment.
Applicant( age < 21 )
then
/* This is a multi-line comment
in the rule actions. */
$application.setApproved( false );
$application.setExplanation( "Underage" );
end
DRL中的错误信息
如果规则有问题,会按照如下格式输出
-
1st Block: Error code
-
2nd Block: Line and column in the DRL source where the error occurred
-
3rd Block: Description of the problem
-
4th Block: Component in the DRL source (rule, function, query) where the error occurred
-
5th Block: Pattern in the DRL source where the error occurred (if applicable)