规则引擎Drools快速入门

规则引擎简介

规则引擎,全称为业务规则管理系统,英文名为BRMS(即Business Rule Management System)。规则引擎实现了将业务决策从应用程序中分离出来,接收数据的输入,解释业务规则,并根据业务规则做出业务决策。规则引擎就是这样一个输入输出平台。现在比较流行的规则引擎之一为Drools,一款由JBoss组织提供的基于Java语言开发的开源规则引擎,Drools是KIE项目的一部分,Kie:Knowledge is everything, Jboss一些列项目的总称。

规则引擎主要的应用场景

对于一些比较复杂的业务规则并且业务规则可能频繁的变动的系统比较合适使用规则引擎,如下:

  1. 风险控制系统——风险贷款、风险评估
  2. 反欺诈项目——银行贷款、征信验证
  3. 决策平台系统——财务计算
  4. 促销平台系统——满减、打折、加价购

Drools介绍

drools是一款由JBoos组织提供的基于Java语言开发的开源规则引擎,可以将复杂的业务规则从硬编码中剥离出来,以规则脚本的形式放在文件或者特定的存储介质中(例如数据库中),使得业务规则的变更不需要修改项目代码、不用重启服务器就可以在线上环境立即生效。

drools官网地址

drools源码下载地址

  • 使用规则引擎有哪些优势:
    • 业务规则与系统代码分离,实现业务规则的集中管理
    • 在不重启服务的情况下可以随时对业务规则进行扩展和维护
    • 可以动态修改业务规则,从而快速响应需求变更
    • 规则引擎是相对独立的,只关心业务规则,是的业务分析人员也可以参与编辑、维护系统的业务规则
    • 减少硬编码业务规则的成本和风险
    • 使用规则引擎提供的规则编辑工具,使复杂的业务规则变得简单

在项目中使用drools时,既可以单独使用也可以整合springboot使用。如果单独使用需要导入如下maven坐标即可:

1
2
3
4
5
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.10.0.Final</version>
</dependency>

如果我们使用IDEA开发drools应用,IDEA中已经集成了drools插件。

drools API开发步骤如下

drools开发步骤

Drools快速入门

业务场景说明

用户购买的商品总额和对应的积分赠送规则如下:

1
2
3
4
100元以下,不加积分
100元~500元,加100积分
500元~1000元,加500积分
1000元以上,加1000积分

开发实现

第一步:创建maven工程droolsDemo并导入相关maven坐标

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.10.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

第二步:在工程中的resources下创建META-INF文件夹,并在文件夹下创建kmodule.xml配置文件,配置文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<!--
name:指定kbase的名称,可以任意,但是需要唯一
packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
default:指定当前kbase是否为默认
-->
<kbase name="myKbase1" packages="rules" default="true">
<!--
name:指定ksession名称,可以任意,但是需要唯一
default:指定当前session是否为默认
-->
<ksession name="ksession-rule" default="true"/>
</kbase>
</kmodule>

注意: 上面配置文件的名称和位置都是固定写法,不能更改

kmodule 中可以包含一个到多个kbase,分别对应drl的规则文件

kbase 需要一个唯一的name,可以去任意字符串

packages 为drl文件所在的resource目录下的路径。(注意区分drl文件中的package与此处的package不一定相同。多个包用逗号分隔。默认情况下会扫描resources目录及子目录下所有规则文件)

kbase的default属性,表示当前KieBase是不是默认的,如果时默认的规则不用名称就可以查找到该KieBase,但每个module最多只能有一个默认KieBase

kbase下面可以有一个或者多个ksession,ksession的name属性必须设置,且必须唯一

第三步:创建实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.lhb.entity;

public class Order {
/** 订单原价 */
private int amout;
/** 积分 */
private int score;


public int getAmout() {
return amout;
}

public void setAmout(int amout) {
this.amout = amout;
}

public int getScore() {
return score;
}

public void setScore(int score) {
this.score = score;
}

@Override
public String toString() {
return "Order{" +
"amout=" + amout +
", score=" + score +
'}';
}
}

第四步:在resources下创建rules目录,并且添加规则文件score-rules.drl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package rules

import com.lhb.entity.Order

//规则1:100元以下, 不加分
rule "score_1"
when
$s : Order(amout <= 100)
then
$s.setScore(0);
System.out.println("成功匹配到规则1:100元以下, 不加分 ");
end

//规则2:100元-500元 加100分
rule "score_2"
when
$s : Order(amout > 100 && amout <= 500)
then
$s.setScore(100);
System.out.println("成功匹配到规则2:100元-500元 加100分 ");
end
//规则3:500元-1000元 加500分
rule "score_3"
when
$s : Order(amout > 500 && amout <= 1000)
then
$s.setScore(500);
System.out.println("成功匹配到规则3:500元-1000元 加500分 ");
end
//规则4:1000元 以上 加1000分
rule "score_4"
when
$s : Order(amout > 1000)
then
$s.setScore(1000);
System.out.println("成功匹配到规则4:1000元 以上 加1000分 ");
end

这个规则文件就是描述了,当符合条件的时侯,做什么事情,每当规则有变动的时候,我们只需要修改规则文件,然后重新加载即可

第五步:编写单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.lhb.test;

import com.lhb.entity.Order;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class TestDrools {
@Test
public void test1(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
//会话对象,用于和规则引擎交互
KieSession kieSession = kieContainer.newKieSession();
//构造订单对象,设置订单金额,由规则引擎计算获得的积分
Order order = new Order();
order.setAmout(200);

//将数据交给规则引擎,规则引擎会根据提供的数据进行规则匹配
kieSession.insert(order);

//激活规则引擎,如果匹配成功则执行规则
kieSession.fireAllRules();
//关闭会话
kieSession.dispose();
//打印结果;
System.out.println("订单提交之后积分:"+order.getScore());
}
}

规则引擎构成

drools规则引擎由以下三个部分构成:

  • Working Memory(工作内存)
  • Rule Base(规则库)
  • Inference Engine(推理引擎),其中推理引擎又包括以下部分:
    • Pattern Matcher(匹配器)具体匹配哪个规则,由这一个来完成
    • Agenda(议程)
    • Execution Engine(执行引擎)

如下图

image-20220708215409773

相关概念说明

Working Memory: 工作内存,drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配,所以我们开发的应用程序只需要将我们的数据插入到Working Memory中即可,例如上面案例中,调用kieSession.insert(order)就是将order对象插入到了工作内存中。

Fact: 事实,是指在drools规则应用当中,将一个普通的JavaBean插入到Working Memory后的对象就是Fact对象,例如上面案例中的Order对象就是输入Fact对象。Fact对象时我们的应用和规则引擎进行数据交互的桥梁或通道。

Rule Base: 规则库,我们在规则文件中定义的规则都会被加载到规则库中

Pattern Matcher: 匹配器,将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。

Agenda: 议程,用于存放通过匹配器进行模式匹配后被激活的规则。

Execution Engine: 执行引擎,执行Agenda中被激活的规则

规则引擎执行过程

规则引擎执行过程

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信