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用于将数据的更改更新到引擎,并通知引擎重新匹配该事实
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
@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
update1执行====People(sex=0, name=达, age=17, drlType=update)
update2执行====People(sex=1, name=达, age=17, drlType=update)
modify 用法与 update类似
rule 'modify'
when
$p : People(drlType == "update" && sex == 1)
then
System.out.println("update3执行====" + $p);
modify($p){
setSex(-1)
}
end
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对象时,值已经被改变,只是不出发规则执行
修改后的测试代码:
@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());
}
修改后的规则:
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
执行结果:
update1执行====People(sex=0, name=达, age=17, drlType=update)
test执行====People(sex=1, name=达, age=17, drlType=update)
2. drools header详解
<div id="import_function"></div>
2.1 import引入java方法 以及 function
导入规则文件需要使用到的外部规则文件或者变量,这里的使用方法跟java相同,但是不同于java的是,这里的import导入的不仅仅可以是一个类,也可以是这个类中的某一个可访问的静态方法
被引入的java方法
package com.ytooo.utils;
public class DroolsStringUtils {
public static boolean isEmpty(String param) {
return param == null || "".equals(param);
}
}
在规则文件中使用
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
执行测试方法,函数执行
@Test
public void impot() {
People people = new People();
people.setDrlType("impot");
session.insert(people);//插入
session.fireAllRules();//执行规则
}
执行结果
false
Hello 达!
<div id="global_detail"></div>
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 定义全局服务以及全局对象
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;
}
}
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脚本中使用全局变量
全局变量以 global 类型 变量名 的方式在规则中定义,在规则Then语句中使用变量名直接对其进行操作
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代码中声明全局变量,并取值
在java代码中使用全局变量,首先要使用 session.setGlobal(变量名,变量)的方式声明变量,其中变量名要与规则中引入变量名相同
若要取值,要使用 session.getGlobal(变量名)的方法,其中变量名要与规则中引入变量名相同
@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());
}
输出结果
[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)
<div id="querys_detail"></div>
2.3 querys 查询
Query语法提供了一种查询working memory中符合约束条件的FACT对象的简单方法。它仅包含规则文件中的LHS部分,不用指定“when”和“then”部分。Query有一个可选参数集合,每一个参数都有可选的类型。如果没有指定类型,则默认为Object类型。
2.3.1 定义drl查询语句
可以定义多个查询参数,在调用查询时传入
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中进行查询
使用session.getQueryResults(查询名, 参数, 参数。。。) 来获取QueryResults匹配对象列表
@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 查询结果
People(sex=5, name=达, age=null, drlType=query)
<div id="declare_detail"></div>
2.4 declare 自定义fact对象
2.4.1 declare在drl规则文件中定义:
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中使用
通过 kieBase.getFactType(域名,实事名)的方式获取实事对象并实例
通过 factType.set(实例,属性名,属性值)的方式来赋值变量
@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 执行结果
People(sex=5, name=达, age=null, drlType=query)
教程代码已提交到ytooo-drools,欢迎star
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。