目录
  • 一、equality modes介绍
    • 1、identity模式
    • 2、equality模式
  • 二、需求
    • 三、如何设置fact对象的equality行为
      • 四、编码实现
        • 1、项目结构图
        • 2、倒入jar包
        • 3、编写Person对象
        • 4、编写kmodule.xml文件
        • 5、编写一个规则文件
        • 6、identity模式测试
          • 1、编写测试代码
          • 2、运行结果
        • 7、equality模式测试
          • 1、编写测试代码
          • 2、运行结果
      • 五、结论
        • 1、identity模式下
          • 2、equality模式下
          • 六、完整代码
            • 七、参考链接

              一、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方法。

              • 多次向工作内存中插入对象,看产生的结果。
              • 插入同一个对象看获取到的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属性来配置。

              其余的配置方法,参考下图:

              深入浅析drools中Fact的equality modes

              四、编码实现

              1、项目结构图

              深入浅析drools中Fact的equality modes

              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对象,那么就输出这个对象的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、运行结果

              深入浅析drools中Fact的equality modes

              具体的解释见上图中的说明。

              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、运行结果

              深入浅析drools中Fact的equality modes

              五、结论

              针对如下代码,看看在不同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

              声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。