drools中Fact的equality|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对象是否是同一个。
kmodule.xml
配置的方法
通过上方的代码可知是通过配置
kbase
下的equalsBehavior
属性来配置。其余的配置方法,参考下图:
文章图片
四、编码实现 1、项目结构图
【drools中Fact的equality|drools中Fact的equality modes】
文章图片
2、倒入jar包
org.drools
drools-bom
pom
7.69.0.Final
import
org.drools
drools-compiler
org.drools
drools-mvel
ch.qos.logback
logback-classic
1.2.11
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。
注意:
需要看2个
equalsBehavior
的取值5、编写一个规则文件
package rulesimport 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
七、参考链接
1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#fact-equality-modes-con_decision-engine
推荐阅读
- 面试|SpringBoot中使用WebSocket的方法
- R中的双变量分布热图
- R中的主成分分析
- Python中使用Dash构建仪表板
- JavaScript|JavaScript 中,用 async + await 和直接同步方式执行有什么区别(意义是什么?)
- 关于Mybatis的mapper文件中${}和#{}的区别和注意事项
- Android中碎片的添加问题
- 在R中使用Highcharter进行数据可视化
- SQL中的远程Python和R
- R中的支持向量机