很自然地,笔者将分成两部分进行讲解。
LHS 是规则条件部分的统称,由 0 个或多个条件元素组成。前面我们已经提到,如果没有条件元素那么默认就是true。
当匹配到对象时,可以将 FACT 对象绑定到指定的变量上。这里的用法类似于 java 的变量定义。绑定之后,在后面就可以直接使用此变量。
rule ...
when
$p : Person()
then
System.out.println( "Person " + $p );
end
// 2 person 的 age 属性值相同
Person( $firstAge : age ) // 绑定
Person( age == $firstAge ) // 约束表达式
其中,前缀$只是一个约定标识,有助于在复杂的规则中轻松区分变量和字段,但并不强制要求必须添加此前缀。
任何一个 JavaBean 中的属性都可以访问,不过对应的属性要提供 getter 方法或isProperty 方法。比如:
Person( age == 50 )
// 与上面拥有同样的效果
Person( getAge() == 50 )
通常情况,我们访问一个内部类的多个属性时会有如下的写法:
Person( name == "mark", address.city == "london", address.country == "uk" )
在 pattern 的约束条件中,可以任何返回结果为布尔类型的 java 表达式。当然,java 表达式也可以和增强的表达式进行结合使用,比如属性访问。可以通过使用括号来更改计算优先级,如在任一逻辑或数学表达式中。
Person( age > 100 && ( age % 10 == 0 ) )
也可以直接使用 java 提供的工具方法来进行操作计算:
Person( Math.round( weight / ( height * height ) ) < 25.0 )
在使用的过程中需要注意,在 LHS 中执行的方法只能是只读的,不能在执行方法过程中改变 FACT 对象的值,否则会影响规则的正确执行。
可使用 Java 的正则表达式进行字符串的匹配,通常情况下使用正则表达式字符串进行匹配,但也支持变量值为正确的表达式的方式。此操作符仅适用于字符串属性。如果属性值为 null,匹配的结果始终为 false。
Cheese( type matches "(Buffalo)?\\S*Mozzarella" )
not matches 方法与 matches 相同,唯一不同的是返回的结果与之相反。
Cheese( type not matches "(Buffalo)?\\S*Mozzarella" )
contains 判断一个集合属性或元素是否包含指定字符串或变量值。仅适用于集合属性。也可以用于替代 String.contains()来检查约束条件。not contains 用法与之相同,结果取反。
CheeseCounter( cheeses contains "stilton" ) // 包含字符串
CheeseCounter( cheeses contains $var ) // 包含变量
Cheese( name contains "tilto" )
Person( fullName contains "Jr" )
String( this contains "foo" )
memberOf 用来检查属性值是否为集合,此集合的表示必须为变量。not memberOf 使用方法相同,结果取反。
CheeseCounter( cheese memberOf $matureCheeses )
str 操作用来比较一个字符串是否以指定字符串开头或结尾,有可以用于比较字符串的长度。
Message( routingValue str[startsWith] "R1" )
Message( routingValue str[endsWith] "R2" )
Message( routingValue str[length] 17 )
in 和 notin 用来匹配一组数据中是否含一个或多个匹配的字符串,使用的方法与数据库中 in 的使用方法相似。待匹配的数据可以是字符串、变量。
Person( $cheese : favouriteCheese )
Cheese( type in ( "stilton", "cheddar", $cheese ) )
RHS 是满足 LHS 条件之后进行后续处理部分的统称,该部分包含要执行的操作的列表信息。RHS 主要用于处理结果,因此不建议在此部分再进行业务判断。如果必须要业务判断需要考虑规则设计的合理性,是否能将判断部分放置于 LHS,那里才是判断条件应该在的地方。
同时,应当保持 RHS 的精简和可读性。如果在使用的过程中发现需要在 RHS 中使用 AND 或 OR 来进行操作,那么应该考虑将
一根规则拆分成多个规则。RHS 的主要功能是对 working memory 中的数据进行 insert、update、delete 或 modify 操作,Drools 提供了相应的内置方法来帮助实现这些功能。下面分别介绍:
insert 的作用与在 Java 类当中调用 KieSession 的 insert 方法效果一样,都是将 Fact 对象插入到当前的 Working Memory 当中,基本用法格式如下:
insert(newSomething());
调用 insert 之后,规则会进行重新匹配,如果没有设置 no-loop 为 true 或 lock-on-active 为 true 的规则,如果条件满足则会重新执行。update、modify、delete 都具有同样的特性,因此在使用时需特别谨慎,防止出现死循环。
规则文件 insert.drl
package com.rules
import com.secbro.drools.model.Product
rule "insert-check"
salience 1
when
$p : Product(type == GOLD);
then
System.out.println("insert-check:insert Product success and it's type is " + $p.getType());
end
rule "insert-action"
salience 2
when
then
System.out.println("insert-action : To
insert the Product");
Product p = new Product();
p.setType(Product.GOLD);
insert(p);
end
打印日志:
insert-action : To insert the Product
insert-check:insert Product success and it's type is GOLD
Fire 2 rules!
根据优先级首先执行 insert 操作的规则,然后执行结果检测。
update 函数可对 Working Memory 中的 FACT 对象进行更新操作,与 StatefulSession 中的 update 的作用基本相同。查看 KnowledgeHelper 接口中的 update 方法可以发现,update函数有多种参数组合的使用方法。在实际使用中更多的会传入 FACT 对象来进行更新操作。
将 Working Memory 中的 FACT 对象删除,与 kession 中的 retract/delete 方法效果一样。同时 delete 函数和 retract 效果也相同,但后者已经被废弃。
modify 是基于结构化的更新操作,它将更新操作与设置属性相结合,用来更改 FACT 对象的属性。语法格式如下:
modify ( ) {
[ , ]*
}
其中
rule "modify stilton"
when
$stilton : Cheese(type == "stilton")
then
modify( $stilton ){
setPrice( 20 ),
setAge( "overripe" )
}
end
更多内容可以访问大佬的博客:http://blog.csdn.net/wo541075754