规则引擎Drools初体验

一、问题引出

业务场景:消费者在图书商城购买图书,下单后需要在支付页面显示订单优惠后的价格。具体优惠规则如下:

规则编号 规则触发条件 优惠金额
1 总价在100元以下 0
2 总价在100元到200元 20元
3 总价在200元到300元 50元
4 总价在300元以上 100元

【思考】:如何实现上述业务逻辑呢?

最容易想到的就是使用分支判断(if-else)来实现,伪代码如下:

// 复制代码
if (sum < 100) {
    return 0;
} else if (sum >= 100 && sum < 200){    
    return 20; 
} else if (sum >= 200 && sum < 300) {   
    return 50; 
} else {
    return 100;
}

通过上面伪代码可以看出,业务规则是通过java代码实现。这种实现方式存在如下问题:

  1. 硬编码实现业务规则难以维护
  2. 硬编码实现业务规则难以应对变化
  3. 业务规则发生变化需要修改代码,重启服务后才能生效

面对此类业务场景,如何实现能比较好的应用规则的增加、修改和删除呢?

答:使用规则引擎!

二、规则引擎概述

2.1 什么是规则引擎

  1. 规则引擎,全称为业务规则管理系统(Business Rule Management System)。规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模板编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。

  2. 规则引擎不是一个具体的技术框架,而是一类系统。目前市面上的规则引擎产品有:drools、VisualRules、iLog等。

规则引擎实现了将业务决策从应用代码中分离出来,接收数据输入、解释业务规则,并根据业务规则做出业务决策 。规则引擎其实就是一个输入输出平台,上述购书满减场景使用规则引擎后效果如下:

系统中引入规则引擎后,业务规则不再以程序代码的形式驻留在系统中,取而代之的是处理规则的规则引擎,业务规则存储在规则库中,完全独立于程序。业务人员可以像管理数据一样对业务规则进行管理(规则管理后台),比如查询、添加、更新、统计、提交业务规则等。业务规则被加载到规则引擎中供应用系统调用。

2.2 使用规则引擎的优势

1、业务规则与系统代码分离,实现业务规则的集中管理

2、可以动态修改业务规则,从而快速响应需求变更

3、规则引擎是相对独立的,只关心业务规则

4、减少了硬编码业务规则的成本和风险

2.3 规则引擎适用场景

1、活动系统----满减、打折、加价购

三、Drools介绍

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

drools官网地址:drools.org/

drools源码下载地址:github.com/kiegroup/dr...

drools API开发步骤如下:

Drools开发实现(案例:消费者购买图书满减优惠)

1、引入依赖

xml 复制代码
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-core</artifactId>
    <version>7.23.0.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.drools/drools-compiler -->
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
    <version>7.23.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-decisiontables</artifactId>
    <version>7.23.0.Final</version>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-templates</artifactId>
    <version>7.23.0.Final</version>
</dependency>
<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-api</artifactId>
    <version>7.23.0.Final</version>
</dependency>

2、配置kmodule文件

在resources下创建META-INF文件夹,并且创建文件kmodule.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="rules">
        <ksession name="all-rules"/>
    </kbase>
</kmodule>

3、规则文件drl

在resources下创建rules文件夹,并创建规则文件。

规则文件如下:

less 复制代码
//图书优惠规则
package rules.book
import com.example.droolsdemo.model.Order

//规则一:所购图书总价在100元以下的没有优惠
rule "book_discount_1"
   when
       $order:Order(originalPrice < 100)
   then
       $order.setRealPrice($order.getOriginalPrice());
       System.out.println("成功匹配到规则一:所购图书总价在100元以下的没有优惠");
end

//规则二:所购图书总价在100到200元的优惠20元
rule "book_discount_2"
   when
       $order:Order(originalPrice < 200 && originalPrice >= 100)
   then
       $order.setRealPrice($order.getOriginalPrice() - 20);
       System.out.println("成功匹配到规则二:所购图书总价在100到200元的优惠20元");
end

//规则三:所购图书总价在200到300元的优惠50元
rule "book_discount_3"
   when
       $order:Order(originalPrice <= 300 && originalPrice >= 200)
   then
       $order.setRealPrice($order.getOriginalPrice() - 50);
       System.out.println("成功匹配到规则三:所购图书总价在200到300元的优惠50元");
end

//规则四:所购图书总价在300元以上的优惠100元
rule "book_discount_4"
   when
       $order:Order(originalPrice >= 300)
   then
       $order.setRealPrice($order.getOriginalPrice() - 100);
       System.out.println("成功匹配到规则四:所购图书总价在300元以上的优惠100元");
end

实体类Order

kotlin 复制代码
@Data
public class Order {
    private Double originalPrice; //初始价格
    private Double realPrice;//实际价格
}

4、测试方法

@Test 复制代码
   public void test() {
       KieServices kieServices = KieServices.Factory.get();
       KieContainer container = kieServices.getKieClasspathContainer();
       //会话对象,用于和规则引擎交互
       KieSession kieSession = container.newKieSession("all-rules");
        
       //构造订单对象,设置原始价格,由规则引擎根据优惠规则计算优惠后的价格
       Order order = new Order();
       order.setOriginalPrice(210D);
        
       //将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配
       kieSession.insert(order);
 
       //激活规则引擎,如果规则匹配成功则执行规则
       kieSession.fireAllRules();
       //关闭会话
       kieSession.dispose();
 
       System.out.println("优惠前原始价格:" + order.getOriginalPrice() +",优惠后价格:" + order.getRealPrice());
   }

测试结果:

相关推荐
代码之光_198028 分钟前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi33 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
颜淡慕潇1 小时前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决
尘浮生2 小时前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
尚学教辅学习资料2 小时前
基于SpringBoot的医药管理系统+LW示例参考
java·spring boot·后端·java毕业设计·医药管理
monkey_meng4 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马4 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng4 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
paopaokaka_luck8 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
码农小旋风10 小时前
详解K8S--声明式API
后端