本文目录导读:

我为你整理了一份关于Drools规则引擎的完整案例解析,涵盖从基础概念到实际业务场景的完整代码演示。
项目基础搭建
Maven依赖配置
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.73.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.73.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.73.0.Final</version>
</dependency>
基础数据模型
// 订单实体
public class Order {
private String orderId;
private Customer customer;
private double amount;
private double discount = 0;
private String discountLevel;
private boolean vip;
private List<String> promotions = new ArrayList<>();
// getters/setters...
}
// 客户实体
public class Customer {
private String name;
private int age;
private int creditScore;
private double totalAmount; // 历史累计消费金额
private String membership; // 会员等级
// getters/setters...
}
// 商品实体
public class Product {
private String productId;
private String category;
private String name;
private double price;
private int stock;
private boolean isPromotional;
// getters/setters...
}
核心业务场景案例
场景1:电商折扣计算系统
业务规则:
- 会员客户享受额外5%折扣
- 累计消费超过10000元享受金卡会员折扣
- 订单金额超过500元且非促销商品,享受10%折扣
- 同时满足多个条件时,折扣可叠加
规则文件 discount-rules.drl:
package com.example.drools.rules
import com.example.drools.model.Order;
import com.example.drools.model.Customer;
// 规则1:普通会员折扣
rule "Member Discount-5%"
when
$customer: Customer(membership == "VIP" && totalAmount >= 5000)
$order: Order(vip == true, discount < 0.15)
then
$order.setDiscount($order.getDiscount() + 0.05);
$order.setDiscountLevel("VIP会员折扣");
System.out.println("应用VIP会员5%折扣");
update($order);
end
// 规则2:大额订单折扣
rule "Large Order Discount-10%"
when
$order: Order(amount > 500, discount < 0.20)
then
$order.setDiscount($order.getDiscount() + 0.10);
$order.setDiscountLevel("大额订单优惠");
System.out.println("应用大额订单10%折扣");
update($order);
end
// 规则3:银联支付优惠
rule "UnionPay Discount-3%"
when
$order: Order(promotions contains "UnionPay", discount < 0.25)
then
$order.setDiscount($order.getDiscount() + 0.03);
$order.getPromotions().add("银联支付优惠");
System.out.println("应用银联支付3%折扣");
update($order);
end
// 规则4:新客首单优惠
rule "New Customer First Order"
when
$customer: Customer(totalAmount == 0)
$order: Order()
then
$order.setDiscount($order.getDiscount() + 0.15);
$order.setDiscountLevel("新客首单优惠");
System.out.println("应用新顾客15%折扣");
update($order);
end
调用代码:
public class DiscountCalculator {
private static KieContainer kieContainer;
static {
KieServices kieServices = KieServices.Factory.get();
kieContainer = kieServices.newKieClasspathContainer();
}
public static Order calculateDiscount(Order order) {
KieSession kieSession = kieContainer.newKieSession("discount-session");
kieSession.insert(order);
kieSession.insert(order.getCustomer());
kieSession.fireAllRules();
kieSession.dispose();
// 计算最终金额
double finalAmount = order.getAmount() * (1 - order.getDiscount());
order.setFinalAmount(finalAmount);
return order;
}
public static void main(String[] args) {
// 测试案例
Customer customer = new Customer();
customer.setName("张三");
customer.setTotalAmount(12000);
customer.setMembership("VIP");
Order order = new Order();
order.setOrderId("ORD001");
order.setCustomer(customer);
order.setAmount(800);
order.setVip(true);
order.getPromotions().add("UnionPay");
Order result = calculateDiscount(order);
System.out.println("订单原价:" + order.getAmount());
System.out.println("总折扣率:" + (result.getDiscount() * 100) + "%");
System.out.println("最终金额:" + result.getFinalAmount());
}
}
场景2:风控可疑交易检测
业务规则:
- 单笔交易超过50000元且时间在凌晨0-5点,高风险
- 5分钟内连续多笔交易累计超过30000元,中高风险
- 新开户3天内大额交易,高风险
- CEO/高管账户大额交易,允许但需通知
规则文件 risk-rules.drl:
package com.example.drools.risk
import java.time.LocalDateTime;
import com.example.drools.model.Transaction;
import com.example.drools.model.User;
// 规则1:凌晨大额交易检测
rule "Detect Late Night Major Transaction"
when
$transaction: Transaction(amount > 50000)
eval(判断交易时间是否在凌晨0-5点)
$user: User(accountType != "CEO")
then
TransactionAlert alert = new TransactionAlert();
alert.setLevel("HIGH");
alert.setType("凌晨大额交易");
alert.setTransactionId($transaction.getTransactionId());
alert.setDescription("疑似洗钱行为,金额超过5万且时间异常");
insert(alert);
drools.halt();
end
// 规则2:高频连续交易检测
rule "Detect Rapid Multiple Transactions"
when
$user: User()
$transactions: List(size > 3) from collect
(Transaction(userId == $user.getUserId(),
timestamp > $user.getLastCheckedTime()))
eval(累计金额超过30000)
then
TransactionAlert alert = new TransactionAlert();
alert.setLevel("MEDIUM_HIGH");
alert.setType("高频交易");
alert.setUserId($user.getUserId());
alert.setTransactionCount($transactions.size());
insert(alert);
end
// 规则3:新开户交易限制
rule "New Account Transaction Monitoring"
when
$user: User(accountAge <= 3)
$transaction: Transaction(amount > 20000, userId == $user.getUserId())
then
TransactionAlert alert = new TransactionAlert();
alert.setLevel("HIGH");
alert.setType("新账户异常");
insert(alert);
end
// 规则4:高管账户通知(非拦截)
rule "CEO Account Notification"
when
$user: User(accountType == "CEO", status == "ACTIVE")
$transaction: Transaction(amount >= 100000, userId == $user.getUserId())
then
TransactionNotification notification = new TransactionNotification();
notification.setType("CEO交易确认");
notification.setMessage("高管大额交易需人工确认");
insert(notification);
end
场景3:货物配送路径优化
业务规则:
- 依据邮编和距离选择最近配送中心
- 考虑货物重量、体积、紧急程度
- 如果配送中心库存不足,自动寻找替代方案
- 包裹丢失时自动触发理赔流程
// 规则1:超出配送范围检测
rule "Out of Delivery Range"
when
$package: PackageObject(deliveryCode != null )
$address: Address(scope == "distance" || $package.getDistance() > 50)
then
System.out.println("该地址超出配送范围,请联系客服");
retract($package);
// 触发特殊流程
insert(new DeliveryException($package, "超出配送范围"));
end
// 规则2:紧急包裹优先处理
rule "Priority Emergency Package"
when
$package: PackageObject(priority == "EMERGENCY",
deliveryTime > 8,
deliveryTime <= 10)
$carrier: Carrier(freeCapacity > $package.getWeight())
then
assignPackageToCarrier($package, $carrier);
update($carrier);
end
决策表(Excel)案例
Excel决策表结构:
| RuleSet | package: com.example.drools.rules | | |----------|----------------------------------|--| | Import | com.example.drools.model.Order | | | Notes | 折扣计算规则决策表 | | |----------------------------------------------------------------| | RuleTable 折扣计算 | | | | 触发条件 | 属性 | 成员属性 | 结果 | |----------|--------------------------|-----------------|------------| | 条件 | 会员等级 | 订单金额 | 折扣率 | | 条件 | 枚举类型 | double | double | | VIP | 金卡会员 | 金额 > 1000 | 0.15 | | 普通用户 | 无会员 | 金额 > 2000 | 0.10 | | 新用户 | 首单 | 任意金额 | 0.20 |
复杂事件处理(CEP)案例
实时监控系统
package com.example.drools.cep
import com.example.drools.model.SensorData;
import java.util.Date;
import java.util.concurrent.TimeUnit;
// 定义事件窗口和时序逻辑
declare SensorAlarm
@role(event)
@timestamp(timestamp)
@expires(24h)
end
// 连续高频异常检测
rule "Detect Continuous High Temperature"
when
// 在10秒内连续3次高温报警
$threshold : Number(doubleValue > 85) from accumulate(
SensorData(time > currentTime - 10s, temperature > 80),
count($count))
$count : Number(intValue >= 3)
then
System.out.println("设备温度异常!连续高温报警次数:" + $count);
insert(new SensorAlarm("HIGH_TEMPERATURE",
"设备连续高温,需要停机检查"));
end
完整项目配置(kmodule.xml)
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules" packages="com.example.drools.rules">
<ksession name="discount-session" type="stateful"/>
<ksession name="stateless-session" type="stateless"/>
</kbase>
<kbase name="risk-rules" packages="com.example.drools.risk">
<ksession name="risk-session" type="stateful"/>
</kbase>
<kbase name="cep-rules" packages="com.example.drools.cep">
<ksession name="cep-session" type="stateful">
<clock type="realtime"/>
</ksession>
</kbase>
</kmodule>
性能优化与最佳实践
规则冲突解决
// 设置规则优先级
rule "High Priority Rule"
salience 100 // 数值越大优先级越高
when
// 条件
then
// 执行逻辑
end
// 使用组和议程
rule "Group A Rule"
agenda-group "main"
activation-group "critical"
end
rule "Alternating Rule"
agenda-group "main"
activation-group "alternating"
end
动态规则加载
public class DynamicRuleLoader {
public static KieSession loadRuleFromString(String ruleContent) {
KieHelper helper = new KieHelper();
helper.addContent(ruleContent, ResourceType.DRL);
KieBase kbase = helper.build();
return kbase.newKieSession();
}
public static void updateRuleInRuntime(KieSession session, String newRule) {
// 重新加载并替换规则
}
}
大数据量优化
// 使用无状态会话
StatelessKieSession statelessSession = kContainer.newStatelessKieSession("stateless-session");
statelessSession.execute(orderList);
// 启用增量编译
KieServices kieServices = KieServices.Factory.get();
KieRepository kr = kieServices.getRepository();
KieBuilder kieBuilder = kieServices.newKieBuilder(kr);
kieBuilder.setIncremental(true);