Contents

Drools 反向链

1. 概述

在本文中,我们将了解什么是反向链接以及如何将它与 Drools 一起使用。

本文是展示Drools 业务规则引擎 系列的一部分。

2. Maven依赖

让我们从导入 drools-core依赖 项开始:

<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>7.4.1.Final</version>
</dependency>

3. 前向链

首先,通过前向链,我们从分析数据开始,然后得出一个特定的结论。

应用正向链的一个例子是通过检查节点之间已知的连接来发现新路由的系统。

4. 反向链

与前向链相反,后向链直接从结论(假设)开始,并通过回溯一系列事实来验证它。

在比较前向链和后向链时,第一个可以描述为“数据驱动”(数据作为输入),而后一个可以描述为“事件(或目标)驱动”(目标作为输入)。

应用反向链的一个示例是验证是否存在连接两个节点的路由。

5. Drools 反向链

Drools 项目主要是作为前向链系统创建的。但是,从 5.2.0 版本开始,它也支持反向链。

让我们创建一个简单的应用程序并尝试验证一个简单的假设——如果中国的长城在地球上。

5.1. 数据

让我们创建一个简单的事实库来描述事物及其位置:

  1. Planet Earth
  2. Asia, Planet Earth
  3. China, Asia
  4. Great Wall of China, China

5.2. 定义规则

现在,让我们创建一个名为BackwardChaining.drl的“.drl”文件,我们将把它放在*/resources/com/blogdemo/drools/rules/*中。这将包含示例中使用的所有必要查询和规则。

将利用反向链的主要belongsTo查询可以写成:

query belongsTo(String x, String y)
    Fact(x, y;)
    or
    (Fact(z, y;) and belongsTo(x, z;))
end

此外,让我们添加两条规则,以便轻松查看我们的结果:

rule "Great Wall of China BELONGS TO Planet Earth"
when
    belongsTo("Great Wall of China", "Planet Earth";)
then
    result.setValue("Decision one taken: Great Wall of China BELONGS TO Planet Earth");
end
rule "print all facts"
when
    belongsTo(element, place;)
then
    result.addFact(element + " IS ELEMENT OF " + place);
end

5.3. 创建应用程序

现在,我们需要一个 Java 类来表示事实:

public class Fact {
 
    @Position(0)
    private String element;
    @Position(1)
    private String place;
    // getters, setters, constructors, and other methods ...    
}

在这里,我们使用*@Position*注释告诉应用程序 Drools 将为这些属性提供值的顺序。

此外,我们将创建表示结果的 POJO:

public class Result {
    private String value;
    private List<String> facts = new ArrayList<>();
 
    //... getters, setters, constructors, and other methods
}

现在,我们可以运行示例:

public class BackwardChainingTest {
    @Before
    public void before() {
        result = new Result();
        ksession = new DroolsBeanFactory().getKieSession();
    }
    @Test
    public void whenWallOfChinaIsGiven_ThenItBelongsToPlanetEarth() {
        ksession.setGlobal("result", result);
        ksession.insert(new Fact("Asia", "Planet Earth"));
        ksession.insert(new Fact("China", "Asia"));
        ksession.insert(new Fact("Great Wall of China", "China"));
        ksession.fireAllRules();
        
        assertEquals(
          result.getValue(),
          "Decision one taken: Great Wall of China BELONGS TO Planet Earth");
    }
}

在执行测试用例时,它们会添加给定的事实(“Asia belongs to Planet Earth”,“China belongs to Asia*”,“Great Wall of China belongs to China”)。

之后,使用BackwardChaining.drl中描述的规则处理事实,该规则提供递归查询belongsTo(String x, String y)

该查询由使用反向链接的规则调用,以查找假设(“Great Wall of China BELONGS TO Planet Earth”)是真还是假。