Drools规则引擎 系列教程(三)Drools规则语法 & RHS动作 & header详解

Drools规则引擎 系列教程(三)Drools规则语法 & RHS动作 & header详解

Drools规则引擎 系列教程(一)SpringBoot整合 & 快速集成上手

Drools规则引擎 系列教程(二)Drools规则语法 & LHS 条件

Drools规则引擎 系列教程(四)Drools 主要API & 决策表

教程代码已提交到ytooo-drools,欢迎star

1. RHS动作

  RHS 部分定义了当LHS满足是要进行的操作,规则操作的主要目的是在Drools引擎的工作内存中插入,删除或修改数据。RHS中可以编写代码,可以使用LHS 部分当中定义的绑定变量名以及drl头部定义的全局变量。在RHS当中如果需要条件判断,那么请重新考虑将其放在 LHS 当中,否则就违背了使用规则的初衷。

1.2. 主要操作

动作 描述
set 给属性赋值
modify 将改变通知drolls引擎
update 将改变通知drolls引擎
insert 将新实事插入到drools引擎的工作
insertLogical insert增强版,需声明撤回事件,或待不在匹配条件后自动撤回
delete 删除实事

1.3. Update

  Update用于将数据的更改更新到引擎,并通知引擎重新匹配该事实

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.ytooo.updat
dialect "java"
import com.ytooo.bean.People

rule 'update1'
when
$p : People(drlType == "update" && sex == 0)
then
System.out.println("update1执行====" + $p);
$p.setSex(1);
update($p)
end
rule 'update2'
when
$p : People(drlType == "update" && sex == 1)
then
System.out.println("update2执行====" + $p);
end
1
2
3
4
5
6
7
8
9
10
11
@Test
public void update() {

People people = new People();
people.setName("达");
people.setSex(0);
people.setAge(17);
people.setDrlType("update");
session.insert(people);//插入
session.fireAllRules();//执行规则
}

当规则1执行后,通过update($p)改变对象值,并重新触发规则2

1
2
update1执行====People(sex=0, name=达, age=17, drlType=update)
update2执行====People(sex=1, name=达, age=17, drlType=update)
modify 用法与 update类似
1
2
3
4
5
6
7
8
9
rule 'modify'
when
$p : People(drlType == "update" && sex == 1)
then
System.out.println("update3执行====" + $p);
modify($p){
setSex(-1)
}
end
1
2
3
update1执行====People(sex=0, name=达, age=17, drlType=update)
update2执行====People(sex=1, name=达, age=17, drlType=update)
update3执行====People(sex=1, name=达, age=17, drlType=update)
特别注意,当在then中改变变量属性值,但不使用update语句时,在调用测试方法中,打印people对象时,值已经被改变,只是不出发规则执行

  修改后的测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void update() {

People people = new People();
people.setName("达");
people.setSex(0);
people.setAge(17);
people.setDrlType("update");
session.insert(people);//插入
session.fireAllRules();//执行规则
System.out.println("test执行====" + people.toString());
}

  修改后的规则:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.ytooo.updat
dialect "java"
import com.ytooo.bean.People

rule 'update1'
when
$p : People(drlType == "update" && sex == 0)
then
System.out.println("update1执行====" + $p);
$p.setSex(1);
// update($p)
end
rule 'update2'
when
$p : People(drlType == "update" && sex == 1)
then
System.out.println("update2执行====" + $p);
end
rule 'modify'
when
$p : People(drlType == "update" && sex == 1)
then
System.out.println("update3执行====" + $p);
modify($p){
setSex(-1)
}
end

  执行结果:

1
2
update1执行====People(sex=0, name=达, age=17, drlType=update)
test执行====People(sex=1, name=达, age=17, drlType=update)

2. drools header详解

2.1 import引入java方法 以及 function

  导入规则文件需要使用到的外部规则文件或者变量,这里的使用方法跟java相同,但是不同于java的是,这里的import导入的不仅仅可以是一个类,也可以是这个类中的某一个可访问的静态方法

被引入的java方法
1
2
3
4
5
6
7
package com.ytooo.utils;

public class DroolsStringUtils {
public static boolean isEmpty(String param) {
return param == null || "".equals(param);
}
}
在规则文件中使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.rules.impor
dialect "java"
import com.ytooo.bean.People
import function com.ytooo.utils.DroolsStringUtils.isEmpty

function String hello(String applicantName) {
return "Hello " + applicantName + "!";
}

rule "impot"

when
$p : People(drlType == "impot")
then
System.out.println(isEmpty("我"));
System.out.println(hello("达"));
end
执行测试方法,函数执行
1
2
3
4
5
6
7
 @Test
public void impot() {
People people = new People();
people.setDrlType("impot");
session.insert(people);//插入
session.fireAllRules();//执行规则
}
执行结果
1
2
false
Hello 达!

2.2 Global 全局变量

  Drools规则文件中的全局变量(global variables)是规则文件代码与java代码之间相互交互的桥梁,我们可以利用全局变量让规则文件中的程序使用java代码中的基本变量、缓存信息或接口服务等等。

2.2.1 基本语法:

global 类型 变量名

例如:
global java.util.List list

2.2.2 使用全局变量来传递数据样例

   全局变量可以是一个services或者一个对象,来方便drolls与java之间的数据传输

2.2.2.1 定义全局服务以及全局对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.ytooo.globa;

import com.ytooo.bean.People;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Youdmeng on 2020/1/14 0014.
*/
@Service
public class GloableService {

public static List<People> getPeoples() {
List<People> peoples = new ArrayList<>();
peoples.add(new People(1, "春", "global"));
peoples.add(new People(2, "夏", "global"));
peoples.add(new People(3, "秋", "global"));
peoples.add(new People(4, "冬", "global"));
peoples.add(new People(5, "达", "global"));
return peoples;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.ytooo.bean;
import lombok.Data;
/**
* Created by Youdmeng on 2020/1/14 0014.
*/
@Data
public class NumCount {

private int count;

public void plus() {
count = count + 1;
}
}
2.2.2.2 在drl脚本中使用全局变量

&emsp;&emsp;全局变量以 global 类型 变量名 的方式在规则中定义,在规则Then语句中使用变量名直接对其进行操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.ytooo.globa
dialect "java"

import com.ytooo.bean.People
import java.lang.Integer

global com.ytooo.globa.GloableService service
global java.util.List list
global com.ytooo.bean.NumCount numCount

rule "global"
when
People(drlType == "global")
$p : People() from service.getPeoples()
then
list.add($p);
numCount.plus();
end
2.2.2.3 在java代码中声明全局变量,并取值

&emsp;&emsp; 在java代码中使用全局变量,首先要使用 session.setGlobal(变量名,变量)的方式声明变量,其中变量名要与规则中引入变量名相同

&emsp;&emsp; 若要取值,要使用 session.getGlobal(变量名)的方法,其中变量名要与规则中引入变量名相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 @Test
public void global() {
People people = new People();
people.setDrlType("global");
session.insert(people);//插入
//配置全局变量
List<People> list = new ArrayList<>();
NumCount numCount = new NumCount();
GloableService service = new GloableService();
session.setGlobal("list", list);
session.setGlobal("numCount", numCount);
session.setGlobal("service", service);
session.fireAllRules();//执行规则
//取出全局变量值
System.out.println(session.getGlobal("list").toString());
System.out.println((session.getGlobal("numCount")).toString());
}
输出结果
1
2
[People(sex=5, name=达, age=null, drlType=global), People(sex=4, name=冬, age=null, drlType=global), People(sex=3, name=秋, age=null, drlType=global), People(sex=2, name=夏, age=null, drlType=global), People(sex=1, name=春, age=null, drlType=global)]
NumCount(count=5)

2.3 querys 查询

avatar
&emsp;&emsp;Query语法提供了一种查询working memory中符合约束条件的FACT对象的简单方法。它仅包含规则文件中的LHS部分,不用指定“when”和“then”部分。Query有一个可选参数集合,每一个参数都有可选的类型。如果没有指定类型,则默认为Object类型。

2.3.1 定义drl查询语句

&emsp;&emsp; 可以定义多个查询参数,在调用查询时传入

1
2
3
4
5
6
7
8
package com.ytooo.quey
dialect "java"

import com.ytooo.bean.People

query "queryPeople" (String $name,Integer $sex)
$p : People(name == $name, sex == $sex)
end
2.3.2 java中进行查询

&emsp;&emsp; 使用session.getQueryResults(查询名, 参数, 参数。。。) 来获取QueryResults匹配对象列表

1
2
3
4
5
6
7
8
9
10
11
12
13
 @Test
public void query() {
session.insert(new People(1, "春", "query"));
session.insert(new People(2, "夏", "query"));
session.insert(new People(3, "秋", "query"));
session.insert(new People(4, "冬", "query"));
session.insert(new People(5, "达", "query"));
QueryResults results = session.getQueryResults("queryPeople", "达", 5);
for (QueryResultsRow row : results) {
People p = (People) row.get("$p");
System.out.println(p);
}
}
2.3.2 查询结果
1
People(sex=5, name=达, age=null, drlType=query)

2.4 declare 自定义fact对象

2.4.1 declare在drl规则文件中定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.ytooo.declar
dialect "java"

declare Love
feel : String
continued : String
end
rule "love"
when
$l : Love()
then
System.out.println("自定义事件执行: " + $l);
end
2.4.2 在api中使用

&emsp;&emsp;通过 kieBase.getFactType(域名,实事名)的方式获取实事对象并实例
&emsp;&emsp;通过 factType.set(实例,属性名,属性值)的方式来赋值变量

1
2
3
4
5
6
7
8
9
10
@Test
public void declare() throws IllegalAccessException, InstantiationException {

FactType factType = kieBase.getFactType("com.ytooo.declar","Love");
Object obj = factType.newInstance();
factType.set(obj,"feel","sad");
factType.set(obj,"continued","永远");
session.insert(obj);
session.fireAllRules();
}
2.4.3 执行结果
1
People(sex=5, name=达, age=null, drlType=query)




教程代码已提交到ytooo-drools,欢迎star

Drools规则引擎 系列教程(二)Drools规则语法 & LHS 条件

Drools规则引擎 系列教程(四)Drools 主要API & 决策表





更多好玩好看的内容,欢迎到我的博客交流,共同进步&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;胡萝卜啵的博客