1. 概述
本文将介绍什么是反向链接(Backward Chaining)以及如何在Drools中使用它。这是Drools业务规则引擎系列文章的一部分。
2. Maven依赖
首先添加drools-core依赖:
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>9.44.0.Final</version>
</dependency>
3. 正向链接
正向链接(Forward Chaining)从数据出发,通过分析数据逐步推导出结论。典型场景是:通过检查已知节点连接来发现新路线。
4. 反向链接
与正向链接相反,反向链接直接从结论(假设)开始,通过回溯一系列事实来验证其有效性。
两种链接方式的本质区别:
- ✅ 正向链接:数据驱动(输入是数据)
- ⚠️ 反向链接:目标驱动(输入是目标)
典型场景:验证两个节点之间是否存在连接路线。
5. Drools中的反向链接
Drools最初是作为正向链接系统设计的,但从5.2.0版本开始支持反向链接。我们通过一个简单示例来验证假设:长城是否属于地球。
5.1 数据准备
构建简单的事实库,描述事物及其位置关系:
- 地球
- 亚洲,地球
- 中国,亚洲
- 长城,中国
5.2 规则定义
在/resources/com/baeldung/drools/rules/
目录下创建BackwardChaining.drl
文件,包含核心查询和规则:
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
注解指定属性值的传递顺序。再创建结果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");
}
}
执行流程:
- 注入事实(亚洲属于地球、中国属于亚洲、长城属于中国)
- 通过
BackwardChaining.drl
中的递归查询belongsTo(String x, String y)
处理事实 - 使用反向链接验证假设("长城属于地球")的真伪
6. 总结
本文展示了Drools的反向链接功能,通过检索事实列表来验证决策的有效性。完整示例可在GitHub仓库中找到。