Drools 简介
1. 概述
Drools 是一个业务规则管理系统 (BRMS) 解决方案。它提供了一个规则引擎,它处理事实并根据规则和事实处理产生输出。业务逻辑的集中化使得快速、廉价地引入更改成为可能。
它还通过提供一种以易于理解的格式编写规则的工具来弥合业务和技术团队之间的差距。
2.Maven依赖
要开始使用 Drools,我们首先需要在pom.xml中添加几个依赖项:
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-ci</artifactId>
<version>7.1.0.Beta1</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.1.0.Beta1</version>
</dependency>
这两个依赖项的最新版本在 Maven Central Repository 上可用kie-ci 和drools-decisiontables 。
3. Drools 基础
我们将看一下 Drools 的基本概念:
- Facts —— 表示作为规则输入的数据
- Working Memory —— 一个带有Facts的存储,它们用于模式匹配,可以修改、插入和删除
- Rule —— 表示将Facts与匹配操作相关联的单个规则它可以在*.drl文件或在 excel 的Decision Table*文件
- Knowledge Session —— 它拥有触发规则所需的所有资源;所有Facts都插入到会话中,然后触发匹配规则
- Knowledge Base —— 代表 Drools 生态系统中的知识,它包含有关Rules 的资源的信息,并创建Knowledge Session
- ***Module *** —— 一个模块包含多个知识库,可以容纳不同的会话
4.Java配置
要对给定数据触发规则,我们需要实例化框架提供的类,其中包含有关规则文件位置和Facts的信息:
4.1. KieFileSystem
首先,我们需要设置KieFileSystem bean;这是框架提供的内存文件系统。以下代码提供了以编程方式定义规则文件、决策表等 Drools 资源的容器:
public KieFileSystem kieFileSystem() throws IOException {
KieFileSystem kieFileSystem = getKieServices().newKieFileSystem();
for (Resource file : getRuleFiles()) {
kieFileSystem.write(
ResourceFactory.newClassPathResource(
RULES_PATH + file.getFilename(), "UTF-8"));
}
return kieFileSystem;
}
这里RULES_PATH表示规则文件在文件系统上的位置。在这里,我们从类路径中读取文件,如果是 Maven 项目,通常是*/src/main/resources*。
4.2. KieContainer
接下来,我们需要设置KieContainer ,它是特定KieModule的所有KieBases的占位符。KieContainer是在其他 bean 的帮助下构建的,包括KieFileSystem、KieModule和KieBuilder。
在KieBuilder上调用的buildAll()方法构建所有资源并将它们绑定到KieBase。只有当它能够找到并验证所有规则文件时,它才会成功执行:
public KieContainer kieContainer() throws IOException {
KieRepository kieRepository = getKieServices().getRepository();
kieRepository.addKieModule(new KieModule() {
public ReleaseId getReleaseId() {
return kieRepository.getDefaultReleaseId();
}
});
KieBuilder kieBuilder = getKieServices()
.newKieBuilder(kieFileSystem())
.buildAll();
return getKieServices().newKieContainer(kieRepository.getDefaultReleaseId());
}
4.3. KieSession
这些规则通过打开一个KieSession bean 来触发——它可以从KieContainer 中检索:
public KieSession kieSession() throws IOException {
return kieContainer().newKieSession();
}
5. 规则的实施
现在我们已经完成了设置,让我们看一下创建规则的几个选项。
我们将通过一个示例来探索规则的实施,该示例根据申请人当前的薪水和他拥有的工作年限对特定角色进行分类。
5.1. Drools 规则文件 ( .drl )
简单地说,Drools 规则文件包含了所有的业务规则。
规则包括一个When-Then结构,这里的When部分列出了要检查的条件,Then部分列出了满足条件时要采取的操作:
package com.blogdemo.drools.rules;
import com.blogdemo.drools.model.Applicant;
global com.blogdemo.drools.model.SuggestedRole suggestedRole;
dialect "mvel"
rule "Suggest Manager Role"
when
Applicant(experienceInYears > 10)
Applicant(currentSalary > 1000000 && currentSalary <=
2500000)
then
suggestedRole.setRole("Manager");
end
可以通过在KieSession中插入applicant和SuggestedRole事实来触发此规则:
public SuggestedRole suggestARoleForApplicant(
Applicant applicant,SuggestedRole suggestedRole){
KieSession kieSession = kieContainer.newKieSession();
kieSession.insert(applicant);
kieSession.setGlobal("suggestedRole",suggestedRole);
kieSession.fireAllRules();
// ...
}
它在applicant实例上测试两个条件,然后根据这两个条件的满足设置SuggestedRole对象中的Role字段。
这可以通过执行测试来验证:
@Test
public void whenCriteriaMatching_ThenSuggestManagerRole(){
Applicant applicant = new Applicant("David", 37, 1600000.0,11);
SuggestedRole suggestedRole = new SuggestedRole();
applicantService.suggestARoleForApplicant(applicant, suggestedRole);
assertEquals("Manager", suggestedRole.getRole());
}
在这个例子中,我们使用了几个 Drools 提供的关键字。让我们了解它们的用途:
- package —— 这是我们在kmodule.xml中指定的包名,规则文件位于这个包内
- import —— 这类似于 Java 的import语句,在这里我们需要指定我们在KnowledgeSession中插入的类
- global —— 用于为会话定义全局级别变量;这可用于传递输入参数或获取输出参数以汇总会话信息
- dialect —— 方言指定条件部分或操作部分的表达式中使用的语法。默认情况下,方言是 Java。Drools 还支持方言mvel;它是一种用于基于 Java 的应用程序的表达式语言。它支持字段和方法/getter 访问
- rule —— 这定义了一个带有规则名称的规则块
- when —— 这指定了一个规则条件,在这个例子中,检查的条件是*Applicant 有超过十年的experienceInYears 和在一定范围内的currentSalary *
- then —— 块中的条件满足时,该块执行动作。在此示例中,申请人角色设置为经理
5.2. 决策表
决策表提供了在预先格式化的 Excel 电子表格中定义规则的能力。Drools 提供的决策表的优点是即使对于非技术人员来说也很容易理解。
此外,当有相似的规则但具有不同的值时,它很有用,在这种情况下,与在 . drl文件。让我们通过基于产品类型在产品上应用标签的示例来看看决策表的结构:
决策表分为不同的部分,最上面的部分就像一个标题部分,我们在其中指定RuleSet(即规则文件所在的包)、Import(要导入的 Java 类)和Notes(关于规则用途的注释)。
我们定义规则的中心部分称为RuleTable,它将应用于同一域对象的规则分组。
在下一行,我们有列类型CONDITION和ACTION。在这些列中,我们可以访问一行中提到的域对象的属性及其在后续行中的值。
触发规则的机制类似于我们在*.drl*文件中看到的机制。
我们可以通过执行测试来验证应用这些规则的结果:
@Test
public void whenProductTypeElectronic_ThenLabelBarcode() {
Product product = new Product("Microwave", "Electronic");
product = productService.applyLabelToProduct(product);
assertEquals("BarCode", product.getLabel());
}