编辑推荐: |
本文来自于csdn,Drools(JBoss Rules )具有一个易于访问企业策略、易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快、效率高。 |
|
规则文件
在 Drools 当中,一个标准的规则文件就是一个以“.drl”结尾的文本文件,由于它是一个标准的文本文件,所以可以通过一些记事本工具对其进行打开、查看和编辑。规则是放在规则文件当中的,一个规则文件可以存放多个规则,除此之外,在规则文件当中还可以存放用户自定义的函数、数据对象及自定义查询等相关在规则当中可能会用到的一些对象。
一个标准的规则文件的结构代码清单:
除package之外,其它对象在规则文件中的顺序是任意的,也就是说在规则文件当中必须要有一个package声明,同时package 声明必须要放在规则文件的第一行,规则文件当中的package和Java语言当中的package有相似之处,但不完全相同。在Java当中package的作用是用来对功能相似或相关的文件放在同一个package下进行管理,这种package管理既有物理上Java文件位置的管理也有逻辑上的文件位置的管理,在Java当中这种通过package管理文件要求在文件位置在逻辑上与物理上要保持一致;但在Drools 的规则文件当中package 对于规则文件中规则的管理只限于逻辑上的管理,而不管其在物理上的位置如何,这点是规则与Java文件的package的区别。
对于同一package下的用户自定义函数、自定义的查询等,不管这些函数与查询是否在同一个规则文件里面,在规则里面是可以直接使用的,这点和 Java 的同一package里的 Java 类调用是一样的。
规则语言
一个规则可以包含三个部分:唯有attributes部分是可选的,其他都是必填信息:
定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等
条件部分:
即LHS,定义当前规则的条件,如when Message(); 判断当前workingMemory中是否存在Message对象。
结果部分:
即RHS,这里可以写普通java代码,即当前规则条件满足后执行的操作,可以直接调用Fact对象的方法来操作应用
条件部分:
件部分又被称之为 Left Hand Side,简称为 LHS,下文当中,如果没有特别指出,那么所说的 LHS 均指规则的条件部分,在一个规则当中 when 与 then 中间的部分就是 LHS 部分。在 LHS 当中,可以包含 0~n 个条件,如果 LHS 部分没空的话,那么引擎会自动添加一 个 eval(true)的条件,由于该条件总是返回 true,所以 LHS 为空的规则总是返回 true。
LHS 部分是由一个或多个条件组成,条件又称之为 pattern(匹配模式),多个 pattern 之间用可以使用 and 或 or 来进行连接,同时还可以使用小括号来确定 pattern 的优先级
对于一个 pattern 来说“绑定变量名”是可选的,如果在当前规则的 LHS 部分的其它的 pattern 要用到这个对象,那么可以通过为该对象设定一个绑定变量名来实现对其引用,对于绑定变量的命名,通常的作法是为其添加一个“$”符号作为前缀,这样可以很好的与 Fact的属性区别开来;绑定变量不仅可以用在对象上,也可以用在对象的属性上面,命名方法与对象的命名方法相同;“field 约束”是指当前对象里相关字段的条件限制,
规则中 LHS 部分单个pattern (模式) 的情形。
规则中“$customer”是就是一个绑定到 Customer 对象的“绑定变量名”,该规则的 LHS 部分表示,要求 Fact 对象必须是 Customer 类型,该条件满足了那么它的 LHS 会返回 true。
下面这种写法就是包含两种pattern(模式) :
rule "rule1"
when
$customer:Customer(age>20,gender=='male')
Order(customer==$customer,price>1000)
then
....
end |
简单说明一下上面的代码
第一个:pattern(模式) 有三个约束
1、 对象 类型必须是 Cutomer;
2、Cutomer 的 age 要大于 20
3、Cutomer 的 gender 要是 male
第二个:pattern(模式) 有三个约束
1、 对象类型必须是 Order;
2、 Order 对应的 Cutomer 必须是前面的那个 Customer
3、 当前这个 Order 的price 要大于 1000
这两个 pattern 没有符号连接,在 Drools 当中在 pattern 中没有连接符号,那么就用 and 来作为默认连接,所以在该规则的 LHS 部分 中两个pattern(模式)只有都满足了才会返回 true。默认情况下,每行可以用“;”来作为结束符(和 Java 的结束一样),当然行尾也可以不加“;”结尾。
约束连接
对于对象内部的多个约束的连接,可以采用“&&”(and)、“||”(or)和“,”(and)来实现
这三个连接符号如果没有用小括号来显示的定义优先级的话,那么它们的执行顺序是:“&&”(and)、“||”(or)
表面上看“,”与“&&”具有相同的含义,但是有一点需要注意,“,”与“&&”和“||”不能混合使用,也就是说在有“&&”或“||”出现的 LHS 当中,是不可以有“,”连接符出现的,反之亦然
Drools提供了十二中类型比较操作符:如果进行常量比较,必须通过eval(条件)或者对象引用比较对象属性,不能单独使用,这语法与java是一样的
>|<,>=|<=,==|!= 这几个不多说啦
contains | not contains
memberOf | not memberOf
matches | not matches
下面说明一下后面6种的含意
contains:比较操作符 contains 是用来检查一个 Fact 对象的某个字段(该字段要是一个 Collection 或是一个 Array 类型的对象)是否包含一个指定的对象
语法格式:
- Object( field[Collection/Array] contains value)
|
Contains.drl写法
package rules.testwrod
import com.drools.test.Person
import com.drools.test.School
rule test001
when
$s:School();
$p:Person(name contains $s.name);
then
System.out.println("恭喜你,成功的使用了 contains");
end |
JavaAPI写法
package com.drools.test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
public class TestWrod{
public static void main(String[] args){
KieServices kss = KieServices.Factory.get();
KieContainer kc = kss.getKieClasspathContainer();
KieSession ks =kc.newKieSession("session");
School school=new School();
school.setCount(50);
school.setName("一班");
Person person=new Person("一班",30);
FactHandle insert = ks.insert(person);
ks.insert(school);
int count = ks.fireAllRules();
System.out.println("总执行了"+count+"条规则");
ks.dispose();
}
} |
contains只能用于对象的某个 Collection/Array类型的字段与另外一个值进行比较,作为比较的值可以是一个静态的值,也可以是一个变量(绑定变量或者是一个global对象),说的可能有点麻烦,小编在这里给大家再通俗的说一下,其实contains就是用来比较属性值是否与被比较值相同,但是这两个属性名是相同的。
not contains:not contains作用与 contains 作用相反,not contains是用来判断一个Fact对象的某个字段(Collection/Array类型)是不是包含一个指定的对象,和 contains比较符相同,它也只能用在对象的 field当中,举例说明
Contains.drl写法
package rules.testwrod
import com.drools.test.Person
import com.drools.test.School
rule test001
when
$s:School();
$p:Person(age not contains $s.count);
then
System.out.println("恭喜你,成功的使用了not contains");
end |
JavaAPI写法
package com.drools.test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
public class TestWrod{
public static void main(String[] args){
KieServices kss = KieServices.Factory.get();
KieContainer kc = kss.getKieClasspathContainer();
KieSession ks =kc.newKieSession("session");
School school=new School();
school.setCount(50);
school.setName("一班");
Person person=new Person("一班",30);
FactHandle insert = ks.insert(person);
ks.insert(school);
int count = ks.fireAllRules();
System.out.println("总执行了"+count+"条规则");
ks.dispose();
}
} |
结果一定是我们想要的,是因为Person中的属性是age而School的属性是count,就算值相同,属性名不同 在not contains下是成立的。
memberOf:memberOf是用来判断某个Fact对象的某个字段是否在一个集合(Collection/Array)当中,用法与 contains有些类似,但也有不同
memberOf的语法如下:
Object(fieldName memberOf value[Collection/Array]) |
可以看到 memberOf中集合类型的数据是作为被比较项的,集合类型的数据对象位于memberOf 操作符后面,同时在用 memberOf比较操作符时被比较项一定要是一个变量(绑定变量或者是一个 global对象),而不能是一个静态值。如何给全局变量赋值:ksession.setGlobal("list",list);举例说明
memberOf.drl文件
package rules.testwrod
import com.drools.test.Person
global java.util.List list;
rule test001
when
$p:Person(name memberOf list);
then
System.out.println("恭喜你,成功的使用了 memberOf");
end |
JavaAPI写法
package com.drools.test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
public class TestWrod{
public static void main(String[] args){
KieServices kss = KieServices.Factory.get();
KieContainer kc = kss.getKieClasspathContainer();
KieSession ks =kc.newKieSession("session");
List list=new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
Person person=new Person("张三",50);
ks.setGlobal("list",list);
FactHandle insert = ks.insert(person);
ks.insert(school);
int count = ks.fireAllRules();
System.out.println("总执行了"+count+"条规则");
ks.dispose();
}
} |
结果肯定是我们想要的了
not memberOf:该操作符与 memberOf 作用洽洽相反,是用来判断Fact对象当中某个字段值是不是中某个集合(Collection/Array)当中。小编这里就不给读者举例说明,有兴趣的读者可以自己尝试一下。
matches:matches 是用来对某个 Fact 的字段与标准的 Java 正则表达式进行相似匹配,被比较的字符串可以是一个标准的 Java 正则表达式,有一点小编要提醒读者注意,那就是正则表达式字符串当中不用考虑“\”的转义问题。
语法如下:
Object(fieldName matches “正则表达式”) |
举例说明
Matches.drl
package rules.testwrod
import com.drools.test.Person
rule test001
when
$p:Person(name matches "张.*");
then
System.out.println("恭喜你,成功的使用了 matches");
end |
JavaAPI写法
package com.drools.test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
public class TestWrod{
public static void main(String[] args){
KieServices kss = KieServices.Factory.get();
KieContainer kc = kss.getKieClasspathContainer();
KieSession ks =kc.newKieSession("session");
Person person=new Person("张三",30);
FactHandle insert = ks.insert(person);
ks.insert(school);
int count = ks.fireAllRules();
System.out.println("总执行了"+count+"条规则");
ks.dispose();
}
} |
结果如下:
小编这里补充几点:简单来说就是模糊查询,语法是不能是 “*.三”这样的语法是错误的。
该规则是用来查找所有Person对象的 name 属性是不是以“张”字开头,如果满足这一条件那么就将该 Person对象的 name 属性打印出来
not matches:与matches 作用相反,是用来将某个Fact的字段与一个Java标准正则表达式进行匹配,看是不是能与正则表达式匹配。 小编这里就不多写做例子了,建议读者要自己试一下,体验一下结果
语法扩展部分
访问List数据结构
$customer.accounts[3]等同于$customer.getAccounts(3)
访问Map数据结构
$customerMap["123"]等同于$customerMap.get["123"]
|