drools中Fact的equality modes
一、equality modes介绍
在drools中存在如下2种equality modes。
1、identity模式
identity:这是默认的情况。drools引擎使用IdentityHashMap保存所有插入到工作内存中的Fact对象。对于每次插入一个新的对象,则会返回一个新的FactHandle对象。如果是重复插入对象,则返回已经存在的FactHandle对象。
举例:
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
针对以上例子, factHandle1 != factHandle2但是 factHandle2 == factHandle3。即工作内存中会存在2个Person对象。
2、equality模式
equality:drools引擎使用HashMap保存所有插入到工作内存中的Fact对象。在这种模式下,如果向drools中插入一个新的对象,只有这个对象不存在(根据对象的hashcode和equals判断)才会返回一个新的FactHandle否则返回已经存在的FactHandle。
举例:
// 重写了Person对象的hashcode和equals方法
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
针对以上例子, factHandle1 == factHandle2但是 factHandle2 == factHandle3。即工作内存中会存在1个Person对象。
二、需求
我们存在一个Person对象,存在如下3个属性name,age和address,其中重写对象的name和age的hashcode和equals方法。
- 多次向工作内存中插入对象,看产生的结果。
- 插入同一个对象看获取到的FactHandle对象是否是同一个。
三、如何设置fact对象的equality行为
此处介绍一个通过kmodule.xml配置的方法
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase-identity" packages="rules" default="false" equalsBehavior="identity">
<ksession name="ksession-01" default="false" type="stateful"/>
</kbase>
<kbase name="kbase-equality" packages="rules" default="false" equalsBehavior="equality">
<ksession name="ksession-02" default="false" type="stateful"/>
</kbase>
</kmodule>
通过上方的代码可知是通过配置kbase下的equalsBehavior属性来配置。
其余的配置方法,参考下图:

四、编码实现
1、项目结构图

2、倒入jar包
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-bom</artifactId>
<type>pom</type>
<version>7.69.0.Final</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
</dependencies>
3、编写Person对象
public class Person {
private String name;
private Integer age;
private String address;
public Person(String name, Integer age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name) && Objects.equals(age, person.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
注意:
此对象需要重写hashcode和equals方法。
4、编写kmodule.xml文件
在此配置文件中,需要在kbase上指定equalsBehavior,用来确定Fact对象的equality modes。
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase-identity" packages="rules" default="false" equalsBehavior="identity">
<ksession name="ksession-01" default="false" type="stateful"/>
</kbase>
<kbase name="kbase-equality" packages="rules" default="false" equalsBehavior="equality">
<ksession name="ksession-02" default="false" type="stateful"/>
</kbase>
</kmodule>
注意:
需要看2个equalsBehavior的取值
5、编写一个规则文件
package rules
import com.huan.drools.Person
// 定义规则
rule "rule_01"
when
$p: Person()
then
System.out.println(Thread.currentThread().getName() + " name:"+$p.getName()+" age:"+$p.getAge());
end
规则文件中的内容很简单,只要工作内存中存在Person对象,那么就输出这个对象的name和age的值。
6、identity模式测试
1、编写测试代码
public class DroolsApplication {
public static void main(String[] args) {
equalsBehaviorIdentity();
}
private static void equalsBehaviorIdentity() {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
// 注意此处的 ksession-01
KieSession kieSession = kieContainer.newKieSession("ksession-01");
kieSession.addEventListener(new DebugRuleRuntimeEventListener());
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
kieSession.fireAllRules();
kieSession.dispose();
}
}
2、运行结果

具体的解释见上图中的说明。
7、equality模式测试
1、编写测试代码
public class DroolsApplication {
public static void main(String[] args) {
equalsBehaviorEquality();
}
private static void equalsBehaviorEquality() {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("ksession-02");
kieSession.addEventListener(new DebugRuleRuntimeEventListener());
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
kieSession.fireAllRules();
kieSession.dispose();
}
}
2、运行结果

五、结论
针对如下代码,看看在不同equality modes下的行为
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
Person对象的hashcode和equals方法进行重写了,根据构造方法的前2个参数。
1、identity模式下
factHandle1 != factHandle2 因为p1和p2是2个不同的对象。
factHandle2 == factHandle3 因为是p2重复加入工作内存,这个时候工作内存中已经存在了,所以返回之前关联的FactHandle
2、equality模式下
factHandle1 == factHandle2 == factHandle3 因为这种模式下,是需要根据对象的equals和hashcode方法进行比较,而Person对象重写了这2个方法,所以返回的是同一个。
六、完整代码
https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-fact-equality-modes
七、参考链接
drools中Fact的equality modes的更多相关文章
- drools中的条件 when
目录 1.介绍 2.语法结构 3.模式例子 3.1 单个对象匹配 3.2 匹配任何对象 3.3 带条件匹配 3.3.1 注意事项 3.4 嵌套属性的匹配 3.4.1 访问单个嵌套属性 3.4.2 访问 ...
- drools中query的使用
一.背景 我们知道在drools中是存在工作内存的,我们的Fact对象会加入到工作内存中,同时我们自己也可以在drl文件中使用insert/modify/update/delete等方法,修改工作内存 ...
- drools中then部分的写法
目录 1.背景 2.支持的方法 2.1 insert 插入对象到工作内存中 2.1.1 需求 2.1.2 drl文件编写 2.1.3 部分java代码编写 2.1.4 运行结果 2.1.5 结论 2. ...
- drools规则引擎中易混淆语法分析_相互触发导致死循环分析
整理了下最近在项目中使用drools出现的问题,幸好都在开发与测试阶段解决了,未波及到prod. 首先看这样两条规则: /** * 规则1_set默认利率a */ rule "rate_de ...
- 【java规则引擎】之Drools引擎中模拟ReteooStatefulSession内部设计结构
该片文章只是抽取drools中java代码实现的一些代码结构,帮助我们理解drools是如何实现rete算法的. 该部分只是抽取ReteooStatefulSession工作过程中的代码架构 利用了多 ...
- Drools文档(八) 规则语言参考
规则语言参考 概述 Drools有一个"本地"的规则语言.这种格式在标点符号上非常轻,并且通过"扩展器"支持自然语言和领域特定的语言,使语言能够变形到您的问题领 ...
- Drools 7.4.1.Final参考手册(八) 规则语言参考
规则语言参考 概述 Drools有一个“本地”的规则语言.这种格式在标点符号上非常轻,并且通过“扩展器”支持自然语言和领域特定的语言,使语言能够变形到您的问题领域.本章主要与本机规则格式一致.用于表示 ...
- Drools环境搭建(转)
Eclipse3.5安装Drools5.2.0.Final插件 到Drools下载页面(现在是http://www.jboss.org/drools/downloads.html) -下载并解压Dro ...
- JAVA规则引擎 -- Drools
Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...
随机推荐
- Python - time标准库使用与程序计时
- Leetcode刷题之矩阵中的指针用法
矩阵中的指针用法 1 快慢指针 Leetcode27移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度.不要使用额外的数组 ...
- python学习笔记(九)——线程与进程
一.线程 Python 中为我们提供了两个模块来创建线程. _thread threading thread 模块已被废弃.用户可以使用 threading 模块代替.所以,在 Python 中不能再 ...
- SVG Sprite 入门(SVG图标解决方案)
关于浏览器图标解决方案,一直就有很多 CSS Sprite,Icon Font,CSS Icon以及SVG.相对而言svg矢量图标以及支持浏览器自身解析的优点,很多团队都已经在使用了.这篇文章主要说明 ...
- 我的python学习记04
列表,元组,字典的使用一.列表列表的格式:list[元素1,元素2,--]列表也是一个有序集合,下标索引从0开始与字符串类似1.在列表中添加数据append:list.append(添加元素) (在最 ...
- AS之去掉顶部标题栏
在该目录下,将原本<style name的这行代码改为: <style name="Theme.Tongxunlu" parent="Theme.Materi ...
- Jar 包下载以及 maven jar 包配置
学习内容: jar包下载是我们必须掌握的一个内容,不管是使用Maven项目还是其他项目,一般都需要引入外部的 jar 包 jar包下载 下载地址(打不开网址的直接百度搜索 maven reposito ...
- 关于页面中css某些情况下出现不知原因的隔断解决办法
第一种方法:body{margin:0px;padding:0px position:absolute; top:0px;left:0px;} html{ width:100%; overflow-x ...
- Node.js躬行记(17)——UmiJS版本升级
在2020年我刚到公司的时候,公司使用的版本还是1.0,之后为了引入微前端,迫不得已被动升级. 一.从 1.0 到 2.0 在官方文档中,有专门一页讲如何升级的,这个用户体验非常好. 一个清单列的非常 ...
- PyQt5 基础知识(六):展示控件
目录 3. 展示控件 3.1 QLabel 3.1.1 描述 3.1.2 功能作用 3.1.2.1 基本功能 3.1.2.2 文本交互 3.1.2.3 内容操作 3.1.2.3.1 文本字符串 3.1 ...