规则引擎Drools快速入门
规则引擎概述
前言
在项目开发中,我们常常会将不经常变化的代码,使用硬编码到程序中。
但是设计经常变化的业务,这里就需要使用到规则引擎。
规则引擎原理
规则引擎通过将 把算法剥离出程序,你可以保存到TXT文件或者数据库表里面,用的时候再加载回程序。
举例:
- 商业中心人流量大的地方,共享充电宝的价格就上调一些
- 商业中心人流量少的地方,共享充电宝的价格就下调一些
既然费用的算法经常要变动,我们肯定不能把算法写死到程序里面。我们要把算法从程序中抽离,保存到MySQL里面。将来我们要改动计费算法,直接添加一个新纪录就行了,原有记录不需要删改,程序默认使用最新的计费方式。
规则引擎概述
规则引擎,全称为业务规则管理,英文为BRMS(即Business Rule Management System)。
规则引擎的主要思想是将应用程序这种的决策部分分离出来,并使用预定义的语义模式编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。
tips:
规则引擎并不是一个具体的技术框架,而是指的一类系统,即业务规则管理系统。目前市面上具体的规则引擎产品有:drools、VisualRules、iLog等。
规则引擎实现了将业务决策从应用程序代码中分离出来,接收数据输入,解释业务规则,并根据业务规则做出业务决策。规则引擎其实就是一个输入输出平台。
系统中引入规则引擎后,业务规则不再以程序代码的形式驻留在系统中,取而代之的是处理规则的规则引擎,业务规则存储在规则库中,完全独立于程序。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。业务规则被加载到规则引擎中供应用系统调用。
使用规则引擎的优势
使用规则引擎的优势如下:
- 业务规则与系统代码分离,实现业务规则的集中管理
- 在不重启服务的情况下可随时对业务规则进行扩展和维护
- 可以动态修改业务规则,从而快速响应需求变更
- 规则引擎是相对独立的,只关心业务规则,使得业务分析人员也可以参与编辑、维护系统的业务规则
- 减少了硬编码业务规则的成本和风险
- 使用规则引擎提供的规则编辑工具,使复杂的业务规则实现变得的简单
规则引擎应用场景
对于一些存在比较复杂的业务规则并且业务规则会频繁变动的系统比较适合实用规则引擎,如下:
- 风险控制系统——风险贷款、风险评估
- 反欺诈项目——银行贷款、征信验证
- 决策平台系统——财务计算
- 促销平台系统——满减、打折、加价购
Drools介绍
drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。
drools官网地址:https://drools.org/
drools源码下载地址:https://github.com/kiegroup/drools
Drools快速入门
pom依赖
<properties>
<java.version>17</java.version>
<drools.version>8.41.0.Final</drools.version>
</properties>
...
<dependencies>
<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.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
<version>${drools.version}</version>
</dependency>
</dependencies>
添加Drools配置类
package com.zxb.drools.config;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieModule;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 规则引擎配置类
*/
@Configuration
public class DroolsConfig {
private static final KieServices kieServices = KieServices.Factory.get();
// 制定规则文件的路径
private static final String RULES_CUSTOMER_RULES_DRL = "rules/orderScore.drl";
@Bean
public KieContainer kieContainer() {
// 获得Kie容器对象
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
KieModule kieModule = kieBuilder.getKieModule();
return kieServices.newKieContainer(kieModule.getReleaseId());
}
}
配置类说明:
- 定义了一个
KieContainer的Spring Bean,KieContainer用于通过加载应用程序的/resources文件夹下的规则文件来构建规则引擎。 - 创建
KieFileSystem实例并配置规则引擎并从应用程序的资源目录加载规则的DRL文件。 - 使用
KieBuilder实例来构建drools模块。我们可以使用KieSerive单例实例来创建KieBuilder实例。 - 最后,使用
KieService创建一个KieContainer并将其配置为spring bean
创建实体类Order
package com.zxb.drools.model;
public class Order {
private double amount;
private double score;
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
orderScore.drl
创建规则文件 resources/rules/orderScore.drl
// 规则积分规则
package com.order
import com.zxb.drools.model.Order
// 规则一:100元以下 不加分
rule "order_rule_1"
when $order:Order(amount < 100)
then
$order.setScore(0);
System.out.println("成功匹配到规则一:100元以下 不加分");
end
// 规则二:100 - 500 元 加100分
rule "order_rule_2"
when $order:Order(amount >= 100 && amount < 500)
then
$order.setScore(100);
System.out.println("成功匹配到规则二:100 - 500 元 加100分");
end
// 规则三:500 - 1000元 加500分
rule "order_rule_3"
when $order:Order(amount >= 500 && amount < 1000)
then
$order.setScore(500);
System.out.println("成功匹配到规则三:500 - 1000元 加500分");
end
// 规则四:1000元以上 加1000分
rule "order_rule_4"
when
$order:Order(amount >= 1000)
then
$order.setScore(1000);
System.out.println("成功匹配到规则四:1000元以上 加1000分");
end
编写测试类
package com.zxb.drools;
import com.zxb.drools.model.Order;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DroolsDemoApplicationTests {
@Resource
KieContainer kieContainer;
@Test
public void test() {
// 从Kie容器对象中获取会话对象
KieSession kieSession = kieContainer.newKieSession();
// Fact对象, 事实对象
Order order = new Order();
order.setAmount(1300);
// 将Order对象插入到工作内存中
kieSession.insert(order);
// 激活规则, 由Drools框架自动进行匹配,如果规则匹配成功,则执行当前规则
kieSession.fireAllRules();
// 关闭会话
kieSession.dispose();
System.out.println("订单金额: " + order.getAmount() + ", 添加积分: " + order.getScore());
}
}
代码解析:
通过上面的入门案例我们可以发现,使用drools规则引擎主要工作就是编写规则文件,在规则文件中定义跟业务相关的业务规则。规则定义好后就需要调用drools提供的API将数据提供给规则引擎进行规则模式匹配,规则引擎会执行匹配成功的规则并将计算的结果返回给我们。
可能大家会有疑问,就是我们虽然没有在代码中编写规则的判断逻辑,但是我们还是在规则文件中编写了业务规则,这跟在代码中编写规则有什么本质的区别呢?
我们前面其实已经提到,使用规则引擎时业务规则可以做到动态管理。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。这样就可以做到在不重启服务的情况下调整业务规则。
欢迎关注我的公众号【zxb的博客】!

- 感谢你赐予我前进的力量

