本文主要对Drools的使用业务场景做简单介绍。
规则引擎
规则引擎:全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模块编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。
需要注意的是规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。
目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。
规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台。
Drools介绍
drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、不用重启服务器就可以在线上环境立即生效。drools官网地址
:https://drools.org/drools源码下载地址
:https://github.com/kiegroup/drools
- 使用规则引擎能够解决什么问题?
针对复杂的业务规则代码处理,往往存在一下问题:
1、硬编码实现业务规则难以维护;
2、硬编码实现业务规则难以应对变化;
3、业务规则发生变化需要修改代码,重启服务后才能生效;
于是规则引擎Drools便诞生在项目中。。。 - 使用规则引擎的优势如下:
1、业务规则与系统代码分离,实现业务规则的集中管理
2、在不重启服务的情况下可随时对业务规则进行扩展和维护
3、可以动态修改业务规则,从而快速响应需求变更
4、规则引擎是相对独立的,只关心业务规则,使得业务分析人员也可以参与编辑、维护系统的业务规则
5、减少了硬编码业务规则的成本和风险
6、使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单
构成
drools规则引擎由以下三部分构成:
-
Working Memory
:工作内存,drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要将我们的数据插入到Working Memory中即可; -
Rule Base
:规则库,我们在规则文件中定义的规则
都会被加载到规则库中 -
Inference Engine
:推理引擎
其中Inference Engine(推理引擎)又包括:
- Pattern Matcher(匹配器): 具体匹配哪一个规则,由这个完成,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。
- Agenda(议程):用于存放通过匹配器进行模式匹配后被激活的规则。
- Execution Engine(执行引擎):执行Agenda中被激活的规则。
Fact:事实,是指在drools 规则应用当中,**将一个普通的JavaBean插入到Working Memory后的对象就是Fact对象**,Fact对象是我们的应用和规则引擎进行数据交互的桥梁或通道。
规则引擎执行过程
- 规则引擎应用场景
对于一些存在比较复杂的业务规则并且业务规则会频繁变动的系统比较适合使用规则引擎,如下:
1、风险控制系统----风险贷款、风险评估
2、反欺诈项目----银行贷款、征信验证
3、决策平台系统----财务计算
4、促销平台系统----满减、打折、加价购
实战
目录结构:
- pom.xml中引入依赖drools
注意这里在properties标签中设置版本
<properties>
<java.version>1.8</java.version>
<drools.version>7.28.0.Final</drools.version>
</properties>
<!-- start drools -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-internal</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.35.0.Final</version>
</dependency>
<!-- end drools -->
- 在
src/main/resources/META-INF
目录下新建文件kmodule.xml
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.drools.org/xsd/kmodule">
<!--
可以存在多个<kbase>标签;
name属性值可以随意设置;
packages:对应*.drl文件的resources路径
ksession标签必须设置;一个或者多个标签,name属性值唯一
-->
<kbase name="test-rulesKB" packages="rules">
<ksession name="test-rulesKS"/>
</kbase>
</kmodule>
- 在src/main/resources/rules目录下新建
test.drl
文件
package rules
import com.qxy.drools.Customer
rule "customerAge"
no-loop true // 定义当前的规则是否 不允许多次循环执行,默认是 false,也就是当前的规则只要满足条件,可以无限次执行
lock-on-active true //将lock-on-active属性的值设置为true,可避免因某些Fact对象被修改而使已经执行过的规则再次被激活执行。
salience 1
when
$customer:Customer(age < 10)
then
$customer.setAge($customer.getAge() + 1);
update($customer)
System.out.println($customer.getName() + ",age:" + $customer.getAge());
end
- 运行测试
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
/**
* @author qxy
* @date 2020/11/11 11:31 上午
*/
public class DroolTest {
public static void main(String[] args) {
KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
KieSession ksession = kc.newKieSession("test-rulesKS");
Customer customer1 = new Customer();
customer1.setAge(1);
customer1.setName("李三");
Customer customer2 = new Customer();
customer2.setAge(18);
customer2.setName("李四");
ksession.insert(customer1);
ksession.insert(customer2);
ksession.fireAllRules();
ksession.dispose();
}
}