一、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中插入一个新的对象,只有这个对象不存在(依据对象的hashcodeequals判断)才会返回一个新的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办法。

  1. 屡次向工作内存中插入对象,看产生的后果。
  2. 插入同一个对象看获取到的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 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对象,那么就输入这个对象的nameage的值。

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 因为这种模式下,是须要依据对象的equalshashcode办法进行比拟,而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