前面章节我们已经知道了一套完整的规则文件内容构成如下:
关键字 | 描述 |
---|---|
package | 包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用 |
import | 用于导入类或者静态方法 |
global | 全局变量 |
function | 自定义函数 |
query | 查询 |
rule end | 规则体 |
1 global全局变量
定义规则文件
|
定义测试方法
|
运行结果
学习:yingyu count=15 gList.size=2 学习:yuwen count=5 gList.size=2 2 |
2 query查询
query查询提供了一种查询working memory中符合约束条件的Fact对象的简单方法。它仅包含规则文件中的LHS部分,不用指定“when”和“then”部分并且以end结束。具体语法结构如下:
query 查询的名称(可选参数)
LHS
end
具体操作步骤:
编写规则文件
|
编写测试类
|
测试结果
size=2 Student(name=张三, result=null, age=12, sex=null, subjects=null) Student(name=王五, result=null, age=22, sex=null, subjects=null) size=1 Student(name=王五, result=null, age=22, sex=null, subjects=null) |
3 function函数
function关键字用于在规则文件中定义函数,就相当于java类中的方法一样。可以在规则体中调用定义的函数。使用函数的好处是可以将业务逻辑集中放置在一个地方,根据需要可以对函数进行修改。
函数定义的语法结构如下:
function 返回值类型 函数名(可选参数){
//逻辑代码
}
具体操作步骤:
编写规则文件
|
编写测试类
|
4,LHS加强
前面我们已经知道了在规则体中的LHS部分是介于when和then之间的部分,主要用于模式匹配,只有匹配结果为true时,才会触发RHS部分的执行。本章节我们会针对LHS部分学习几个新的用法。
复合值限制in/not in
Object(field in (比较值1,比较值2...))
举例:
$s:Student(name in ("张三","李四","王五"))
$s:Student(name not in ("张三","李四","王五"))
条件元素eval
not用于判断Working Memory中是否存在某个Fact对象,如果不存在则返回true,如果存在则返回false。语法结构如下:
not Object(可选属性约束)
举例:
not Student()
not Student(age < 10)
条件元素exists
exists的作用与not相反,用于判断Working Memory中是否存在某个Fact对象,如果存在则返回true,不存在则返回false。语法结构如下:
exists Object(可选属性约束)
举例:
exists Student()
exists Student(age < 10 && name != null)
可能有人会有疑问,我们前面在LHS部分进行条件编写时并没有使用exists也可以达到判断Working Memory中是否存在某个符合条件的Fact元素的目的,那么我们使用exists还有什么意义?
两者的区别:当向Working Memory中加入多个满足条件的Fact对象时,使用了exists的规则执行一次,不使用exists的规则会执行多次。
例如:
编写规则
package rules; import com.dream21th.drools.study.demo6.Student /* 使用exists的规则 */ rule "demo-exists-1" when exists Student() then System.out.println("规则:使用demo-exists-1的规则触发"); end /** 没有使用exists的规则 **/ rule "demo-exists-2" when Student() then System.out.println("规则:没有使用demo-exists-2的规则触发"); end |
编写测试代码
@Test public void test_exists(){ KieServices kieServices = KieServices.Factory.get(); KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer(); //会话对象,用于和规则引擎交互 KieSession kieSession = kieClasspathContainer.newKieSession(); Student student = new Student(); kieSession.insert(student); kieSession.insert(new Student()); //激活规则引擎,如果规则匹配成功则执行规则 kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("demo-exists")); //关闭会话 kieSession.dispose(); } |
测试结果
规则:使用demo-exists-1的规则触发 规则:没有使用demo-exists-2的规则触发 规则:没有使用demo-exists-2的规则触发 |
上面第一个规则只会执行一次,因为Working Memory中存在两个满足条件的Fact对象,第二个规则会执行两次
规则继承
规则之间可以使用extends关键字进行规则条件部分的继承,类似于java类之间的继承。
例如:
package rules; import com.dream21th.drools.study.demo6.Student rule "demo6_extends_1" when Student(age > 10) then System.out.println("规则:demo6_extends_1触发"); end rule "demo6_extends_2" extends "demo6_extends_1" //继承上面的规则 when /* 此处的条件虽然只写了一个,但是从上面的规则继承了一个条件, 所以当前规则存在两个条件,即Student(age < 20)和Student(age > 10) */ Student(age < 20) then System.out.println("规则:demo6_extends_2触发"); end |
测试代码
@Test public void test_extends(){ KieServices kieServices = KieServices.Factory.get(); KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer(); //会话对象,用于和规则引擎交互 KieSession kieSession = kieClasspathContainer.newKieSession(); Student student = new Student(); student.setAge(28); kieSession.insert(student); //激活规则引擎,如果规则匹配成功则执行规则 kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("demo6_extends")); //关闭会话 kieSession.dispose(); } |
触发结果
规则:demo6_extends_1触发 |
因为规则2继承了规则1,所以规则2的触发条件是age大于10并且小于20 ,由于例子中的是28所以只触发了第一条规则
RHS部分是规则体的重要组成部分,当LHS部分的条件匹配成功后,对应的RHS部分就会触发执行。一般在RHS部分中需要进行业务处理。
在RHS部分Drools为我们提供了一个内置对象,名称就是drools。本小节我们来介绍几个drools对象提供的方法。
halt
package testhalt rule "rule_halt_1" when then System.out.println("规则:rule_halt_1触发"); drools.halt();//立即终止后面所有规则执行 end //当前规则并不会触发,因为上面的规则调用了halt方法导致后面所有规则都不会执行 rule "rule_halt_2" when then System.out.println("规则:rule_halt_2触发"); end |
getWorkingMemory
getWorkingMemory方法的作用是返回工作内存对象。
package testgetWorkingMemory rule "rule_getWorkingMemory" when then System.out.println(drools.getWorkingMemory()); end |
getRule
getRule方法的作用是返回规则对象。
package testgetRule rule "rule_getRule" when then System.out.println(drools.getRule()); end |
我们在进行drl类型的规则文件编写时尽量遵循如下规范:
代码地址:https://gitee.com/dream21th/drools-study/tree/master/demo6