从硬编码到“规则即配置”!SpringBoot 整合 Drools 8 实现电商促销规则动态编排
·
前言
电商促销场景中,满减、折扣、优惠券、会员等级、限时活动等规则频繁变更,传统硬编码方式不仅需要频繁发版,还会让代码充斥大量if-else,维护成本极高。
使用 Drools 8 规则引擎,可将促销逻辑从业务代码中剥离,实现规则动态配置、实时生效、无需重启服务,大幅提升迭代效率,让复杂的优惠叠加逻辑清晰可维护。
本文基于 SpringBoot + Drools 8,从零搭建一套可直接落地的电商促销规则引擎,包含完整代码与实战经验。
二、Drools 到底是什么?
2.1 什么是 Drools?
Drools 是 开源业务规则管理系统(BRMS),基于Java开发,核心是RETE算法(高效规则匹配算法),能快速处理复杂的多条件规则推理。
简单说:Drools 就是一个“规则计算器”。
- 你输入业务数据(Fact)(如订单金额、用户等级)
- 它加载规则文件(DRL)(如满减、折扣逻辑)
- 自动匹配规则并执行,输出决策结果(如最终折扣、积分)
2.2 三大核心概念
1)Fact(事实)
Fact 是传入引擎的业务数据对象,就是我们的Java实体类(如Order、Customer),用于匹配规则条件。
// 订单Fact
public class Order {
private double amount; // 订单金额
private int vipLevel; // VIP等级 0=普通 1=银卡 2=金卡
private double discount;// 折扣金额
}
2)DRL(规则文件)
DRL 是 Drools 规则文件,后缀.drl,用 when-then 语法编写,接近自然语言,一个文件可写多条规则。
// 规则:金卡用户满500减100
rule "gold_vip_full_reduce"
when
$order : Order(amount >= 500, vipLevel == 2)
then
$order.setDiscount($order.getDiscount() + 100);
end
3)Kie 容器
Kie 是 Drools 的核心容器,负责加载规则文件、创建会话、执行规则,Spring Boot 集成后可自动管理。
三、Spring Boot 集成 Drools 8 实战
3.1 场景需求
我们要实现一套叠加式促销规则,需求如下:
- 基础满减:订单金额≥300减50,≥500减100,≥1000减200
- VIP折扣:银卡(1级)9折,金卡(2级)8折(满减后金额计算折扣)
- 新用户优惠:用户注册≤7天,额外减30(可叠加所有规则)
3.2 步骤1:引入依赖
<!-- Drools 核心依赖 -->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>8.41.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>8.41.0.Final</version>
</dependency>
3.3 步骤2:编写 Fact 实体类
Order.java(订单)
public class Order {
// 订单金额(原始)
private double amount;
// VIP等级:0=普通 1=银卡 2=金卡
private int vipLevel;
// 是否新用户(注册≤7天)
private boolean isNewUser;
// 折扣金额(最终计算结果)
private double discount;
// 最终支付金额
private double finalAmount;
// 无参构造,必须,Drools 反射用
public Order() {}
public double getAmount() { return amount; }
public void setAmount(double amount) { this.amount = amount; }
public int getVipLevel() { return vipLevel; }
public void setVipLevel(int vipLevel) { this.vipLevel = vipLevel; }
public boolean isNewUser() { return isNewUser; }
public void setNewUser(boolean newUser) { isNewUser = newUser; }
public double getDiscount() { return discount; }
public void setDiscount(double discount) { this.discount = discount; }
public double getFinalAmount() { return finalAmount; }
public void setFinalAmount(double finalAmount) { this.finalAmount = finalAmount; }
}
3.4 步骤3:编写促销规则文件(promotion.drl)
在 src/main/resources/rules 下创建 promotion.drl,所有规则写在一个文件,清晰易维护:
// 包名(必须和Java类一致)
package com.ecommerce.promotion
// 导入Fact类
import com.ecommerce.model.Order
// 全局变量(可选,用于返回结果)
global com.ecommerce.model.Order orderResult
// 规则1:基础满减 - 满300减50
rule "base_full_reduce_300"
salience 10 // 优先级:数字越大越先执行
when
$order : Order(amount >= 300, amount < 500)
then
$order.setDiscount(50);
System.out.println("执行规则:满300减50");
end
// 规则2:基础满减 - 满500减100
rule "base_full_reduce_500"
salience 10
when
$order : Order(amount >= 500, amount < 1000)
then
$order.setDiscount(100);
System.out.println("执行规则:满500减100");
end
// 规则3:基础满减 - 满1000减200
rule "base_full_reduce_1000"
salience 10
when
$order : Order(amount >= 1000)
then
$order.setDiscount(200);
System.out.println("执行规则:满1000减200");
end
// 规则4:VIP银卡9折(满减后)
rule "vip_silver_discount"
salience 9
when
$order : Order(vipLevel == 1)
then
double afterReduce = $order.getAmount() - $order.getDiscount();
double vipDiscount = afterReduce * 0.1; // 9折=减10%
$order.setDiscount($order.getDiscount() + vipDiscount);
System.out.println("执行规则:银卡9折,额外减" + vipDiscount);
end
// 规则5:VIP金卡8折(满减后)
rule "vip_gold_discount"
salience 9
when
$order : Order(vipLevel == 2)
then
double afterReduce = $order.getAmount() - $order.getDiscount();
double vipDiscount = afterReduce * 0.2; // 8折=减20%
$order.setDiscount($order.getDiscount() + vipDiscount);
System.out.println("执行规则:金卡8折,额外减" + vipDiscount);
end
// 规则6:新用户额外减30
rule "new_user_discount"
salience 9
when
$order : Order(isNewUser == true)
then
$order.setDiscount($order.getDiscount() + 30);
System.out.println("执行规则:新用户额外减30");
end
// 规则7:计算最终金额
rule "calculate_final_amount"
salience 8 // 最后执行
when
$order : Order()
then
double finalAmt = $order.getAmount() - $order.getDiscount();
$order.setFinalAmount(finalAmt > 0 ? finalAmt : 0);
System.out.println("执行规则:最终金额计算完成");
end
关键说明:
salience:规则优先级,数字越大越先执行,确保满减→VIP折扣→新用户→最终计算的顺序。when:条件部分,匹配Fact的属性。then:动作部分,满足条件后执行的逻辑。
3.5 步骤4:Spring Boot 配置 Drools
@Configuration
public class DroolsConfig {
// 配置Kie容器,加载规则文件
@Bean
public KieContainer kieContainer() {
// 加载resources/rules下的所有drl文件
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
// 加载规则文件
kieFileSystem.write(ResourceFactory.newClassPathResource("rules/promotion.drl"));
// 构建Kie容器
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
return kieServices.newKieContainer(kieBuilder.getKieModule().getReleaseId());
}
}
3.6 步骤5:编写促销服务(调用规则引擎)
@Service
public class PromotionService {
@Autowired
private KieContainer kieContainer;
// 计算促销折扣
public Order calculatePromotion(Order order) {
// 每次请求创建一个新的 session,线程安全
KieSession kieSession = kieContainer.newKieSession();
try {
// 1. 把订单对象插入到规则引擎
kieSession.insert(order);
// 2. 执行所有规则
kieSession.fireAllRules();
// 3. 规则执行完,order 本身已经被修改了,直接返回
return order;
} finally {
// 4. 关闭 session,避免内存泄漏
kieSession.dispose();
}
}
}
3.7 步骤6:测试
@Test
void calculatePromotion() {
Order order = new Order();
order.setDiscount(0L);
order.setAmount(1000);
order.setNewUser(true);
order.setVipLevel(2);
Order result = promotionService.calculatePromotion(order);
log.info("计算后的最终价格是:" + result.getFinalAmount());
}
3.8 测试效果

完美实现规则叠加:满减200 + 金卡8折160 + 新用户30 = 总折扣390,最终支付610元。
四、Drools 核心优势
1)规则与代码解耦
- 规则写在独立的
.drl文件中,修改规则无需改Java代码。 - 运营可直接修改规则文件,无需开发介入,沟通成本降为0。
2)动态生效,无需重启
- 配合 Kie Workbench(Drools可视化控制台),可在线编辑规则、实时发布生效,无需重启服务。
- 大促期间紧急改规则,分钟级上线,告别部署等待。
3)复杂规则易维护
- 用
when-then语法,接近自然语言,可读性极强。 - 支持优先级、条件嵌套、规则叠加,复杂促销逻辑也能清晰拆分。
4)高性能规则匹配
- 基于 RETE算法,多条件匹配效率极高,万级规则也能快速执行。
- 适合高并发大促场景,支撑每秒千级订单计算。
五、生产优化
1)KieSession 池化,避免频繁创建销毁
- 问题:每次请求创建/销毁KieSession,性能低、易内存泄漏。
- 优化:使用 Apache Commons Pool2 实现KieSession池化,复用会话,提升吞吐量。
2)规则文件热更新
- 问题:修改drl文件后,需重启服务生效。
- 优化:基于 KieScanner 实现规则文件热更新,监听文件变化自动加载,秒级生效。
3)规则优先级与冲突解决
- 用
salience控制执行顺序,避免规则冲突。 - 复杂规则可拆分多个drl文件,按模块管理(满减规则、VIP规则、新用户规则)。
4)监控与日志
- 记录规则执行日志(哪个规则执行、执行结果),便于问题排查。
- 监控 KieSession 池状态、规则执行耗时,及时发现性能瓶颈。
六、总结
✅ 推荐使用场景
- 电商促销:满减、折扣、优惠券、积分叠加(本文案例)。
- 金融风控:反欺诈、黑名单、交易限额、风险评级。
- 审批流程:多级审批、条件分支、自动审核。
- 保险定价:保费计算、保额规则、理赔条件。
❌ 不推荐使用场景
- 规则简单、变更极少(如固定的状态判断),硬编码更轻量。
- 性能要求极高(每秒万级以上),且规则简单,可考虑自研简易规则引擎。
| ← 上一篇 基于 RocketMQ 延时消息的实现订单超时自动关闭场景 |
记得点赞、关注、收藏哦!
|
下一篇 别再死磕面试题了!Java 面试拼的从来不是背诵 → |
更多推荐



所有评论(0)