本文目录导读:

我来提供一个完整的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-mvel</artifactId>
<version>7.73.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.73.0.Final</version>
</dependency>
业务场景:电商购物车折扣系统
1 创建实体类
package com.example.drools.entity;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
// 商品类
public class Product {
private String name;
private String category; // 电子、图书、食品、服装
private BigDecimal price;
private int quantity;
private boolean isMember; // 是否会员专属商品
// 构造函数
public Product(String name, String category, BigDecimal price, int quantity) {
this.name = name;
this.category = category;
this.price = price;
this.quantity = quantity;
}
// getter/setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
public BigDecimal getPrice() { return price; }
public void setPrice(BigDecimal price) { this.price = price; }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
public boolean isMember() { return isMember; }
public void setMember(boolean member) { isMember = member; }
}
package com.example.drools.entity;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
// 订单类
public class Order {
private Long id;
private List<Product> products = new ArrayList<>();
private BigDecimal totalAmount = BigDecimal.ZERO;
private BigDecimal discountAmount = BigDecimal.ZERO;
private BigDecimal finalAmount = BigDecimal.ZERO;
private String customerLevel; // 普通客户、银卡、金卡、钻石
private boolean hasCoupon;
// 添加商品并计算小计
public void addProduct(Product product) {
if (product != null) {
products.add(product);
BigDecimal subtotal = product.getPrice()
.multiply(BigDecimal.valueOf(product.getQuantity()));
totalAmount = totalAmount.add(subtotal);
}
}
// getter/setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public List<Product> getProducts() { return products; }
public void setProducts(List<Product> products) { this.products = products; }
public BigDecimal getTotalAmount() { return totalAmount; }
public void setTotalAmount(BigDecimal totalAmount) { this.totalAmount = totalAmount; }
public BigDecimal getDiscountAmount() { return discountAmount; }
public void setDiscountAmount(BigDecimal discountAmount) { this.discountAmount = discountAmount; }
public BigDecimal getFinalAmount() { return finalAmount; }
public void setFinalAmount(BigDecimal finalAmount) { this.finalAmount = finalAmount; }
public String getCustomerLevel() { return customerLevel; }
public void setCustomerLevel(String customerLevel) { this.customerLevel = customerLevel; }
public boolean isHasCoupon() { return hasCoupon; }
public void setHasCoupon(boolean hasCoupon) { this.hasCoupon = hasCoupon; }
}
2 创建规则文件
在 resources/rules/ 目录下创建 discount-rules.drl:
package com.example.drools.rules
import com.example.drools.entity.Order;
import com.example.drools.entity.Product;
import java.math.BigDecimal;
import com.example.drools.util.DiscountUtils;
// 规则1:满100元减10元
rule "Full 100 reduce 10"
salience 100 // 优先级,数字越大越先执行
when
$order: Order(totalAmount >= 100)
then
BigDecimal discount = new BigDecimal(10);
$order.setDiscountAmount($order.getDiscountAmount().add(discount));
$order.setFinalAmount($order.getTotalAmount().subtract($order.getDiscountAmount()));
System.out.println("应用规则:满100减10");
end
// 规则2:电子类商品超过200元打95折
rule "Electronics 5% discount over 200"
salience 90
when
$order: Order()
$product: Product(category == "电子", price > 200, quantity > 0) from $order.getProducts()
then
BigDecimal discount = $product.getPrice()
.multiply(BigDecimal.valueOf($product.getQuantity()))
.multiply(new BigDecimal("0.05"));
$order.setDiscountAmount($order.getDiscountAmount().add(discount));
System.out.println("应用规则:电子产品95折优惠 - " + $product.getName());
end
// 规则3:图书类商品全部打9折
rule "Books 10% discount"
salience 85
when
$order: Order()
$product: Product(category == "图书") from $order.getProducts()
then
BigDecimal discount = $product.getPrice()
.multiply(BigDecimal.valueOf($product.getQuantity()))
.multiply(new BigDecimal("0.1"));
$order.setDiscountAmount($order.getDiscountAmount().add(discount));
System.out.println("应用规则:图书9折优惠 - " + $product.getName());
end
// 规则4:银卡及以上客户享受额外9折
rule "VIP customer 10% extra discount"
salience 80
when
$order: Order(customerLevel in ("银卡", "金卡", "钻石"))
then
BigDecimal discount = $order.getTotalAmount()
.multiply(new BigDecimal("0.1"));
$order.setDiscountAmount($order.getDiscountAmount().add(discount));
System.out.println("应用规则:VIP客户9折优惠");
end
// 规则5:有优惠券且金额超过500元
rule "Coupon usage over 500"
salience 75
when
$order: Order(hasCoupon == true, totalAmount >= 500)
then
BigDecimal discount = new BigDecimal(50);
$order.setDiscountAmount($order.getDiscountAmount().add(discount));
System.out.println("应用规则:使用优惠券减50");
end
// 规则6:订单包含20个以上商品,使用积分自动抵扣
rule "Points deduction for bulk orders"
salience 70
when
$order: Order()
$count: Number(intValue >= 20) from accumulate(
$p: Product() from $order.getProducts(),
count($p)
)
then
BigDecimal discount = new BigDecimal(5);
$order.setDiscountAmount($order.getDiscountAmount().add(discount));
System.out.println("应用规则:批量订单积分抵扣5元");
end
// 规则7:赠送礼品(不适合直接打折的模式)
rule "Free gift for high value orders"
salience 65
when
$order: Order(finalAmount < totalAmount)
then
// 这里仅作为演示,实际可以添加礼物对象到订单
System.out.println("订单获得额外赠品");
end
// 规则8:禁止某些组合规则
rule "Cannot combine member and coupon discounts"
salience 0 // 最低优先级,最后执行
when
$order: Order(customerLevel != "普通客户")
$totalDiscount: BigDecimal() from $order.getDiscountAmount()
then
if ($order.getDiscountAmount().compareTo(new BigDecimal(100)) > 0) {
System.out.println("警告:优惠金额超过100元,请人工审核");
}
end
3 工具类
package com.example.drools.util;
import java.math.BigDecimal;
public class DiscountUtils {
// 计算商品小计
public static BigDecimal calculateSubtotal(BigDecimal price, int quantity) {
return price.multiply(BigDecimal.valueOf(quantity));
}
// 计算最终金额
public static BigDecimal calculateFinalAmount(BigDecimal total, BigDecimal discount) {
return total.subtract(discount);
}
// 判断是否可以应用积分抵扣
public static boolean canUsePoints(BigDecimal amount) {
return amount.compareTo(new BigDecimal(100)) >= 0;
}
}
4 核心服务类
package com.example.drools.service;
import com.example.drools.entity.Order;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.StringReader;
@Service
public class DroolsRuleService {
private KieSession kieSession;
@PostConstruct
public void init() {
// 动态创建规则引擎
buildKieSession();
}
private void buildKieSession() {
try {
// 创建KieServices实例
KieServices ks = KieServices.Factory.get();
KieFileSystem kfs = ks.newKieFileSystem();
// 加载规则文件
kfs.write(ResourceFactory.newClassPathResource("rules/discount-rules.drl"));
// 构建KieContainer
KieBuilder kb = ks.newKieBuilder(kfs);
kb.buildAll();
KieRepository kr = ks.getRepository();
KieContainer kContainer = ks.newKieContainer(kr.getDefaultReleaseId());
// 创建会话
kieSession = kContainer.newKieSession();
} catch (Exception e) {
e.printStackTrace();
}
}
// 执行规则匹配
public void executeRules(Order order) {
if (kieSession == null) {
init();
}
// 插入事实对象
kieSession.insert(order);
// 激活规则
kieSession.fireAllRules();
// 计算最终金额
order.setFinalAmount(
order.getTotalAmount().subtract(order.getDiscountAmount())
);
// 释放资源
kieSession.dispose();
// 重新初始化会话(因为dispose之后需要重新创建)
init();
}
}
5 测试类
package com.example.drools.test;
import com.example.drools.entity.Order;
import com.example.drools.entity.Product;
import com.example.drools.service.DroolsRuleService;
import java.math.BigDecimal;
public class TestDrools {
public static void main(String[] args) {
DroolsRuleService service = new DroolsRuleService();
// 创建测试订单
Order order = new Order();
order.setId(1L);
order.setCustomerLevel("金卡");
order.setHasCoupon(true);
// 添加商品
Product phone = new Product("iPhone", "电子", new BigDecimal("6999"), 1);
Product book = new Product("Java编程思想", "图书", new BigDecimal("108"), 2);
Product tshirt = new Product("T恤", "服装", new BigDecimal("99"), 3);
order.addProduct(phone);
order.addProduct(book);
order.addProduct(tshirt);
System.out.println("===== 订单原始信息 =====");
System.out.println("商品数量: " + order.getProducts().size());
System.out.println("原始总金额: " + order.getTotalAmount());
// 执行规则引擎
service.executeRules(order);
System.out.println("\n===== 规则引擎结果 =====");
System.out.println("优惠金额: " + order.getDiscountAmount());
System.out.println("实际支付金额: " + order.getFinalAmount());
}
}
6 Spring Boot 启动类
package com.example.drools;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DroolsApplication {
public static void main(String[] args) {
SpringApplication.run(DroolsApplication.class, args);
}
}
高级特性示例
1 决策表 (Decision Table)
创建 discount-decision.xls 决策表:
// 使用决策表配置转换
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import java.io.FileInputStream;
import java.io.InputStream;
public class DecisionTableExample {
public static void main(String[] args) throws Exception {
// 加载决策表文件
InputStream is = new FileInputStream("discount-decision.xls");
// 编译决策表为DRL规则
SpreadsheetCompiler compiler = new SpreadsheetCompiler();
String drl = compiler.compile(is, InputType.XLS);
System.out.println("生成的DRL规则: \n" + drl);
}
}
2 规则流 (Rule Flow)
// ruleflow-groups.drl
package com.example.drools.rules
import com.example.drools.entity.Order;
rule "Initial check"
ruleflow-group "check"
when
$order: Order(totalAmount > 0)
then
System.out.println("订单金额验证通过");
end
rule "Apply discount"
ruleflow-group "discount"
when
$order: Order()
then
System.out.println("应用折扣规则");
end
性能优化建议
package com.example.drools.config;
import org.kie.api.KieServices;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DroolsConfig {
private static final String RULES_PATH = "rules/";
@Bean
public KieContainer kieContainer() {
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
// 加载所有规则文件
kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_PATH + "discount-rules.drl"));
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);
kieBuilder.buildAll();
// 检查错误
Results results = kieBuilder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
throw new RuntimeException("规则存在错误: \n" + results);
}
return kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
}
@Bean
public KieSession kieSession(KieContainer kieContainer) {
// 使用有状态会话(保证规则执行状态的一致性)
return kieContainer.newKieSession();
}
}
实际运行结果
===== 订单原始信息 =====
商品数量: 3
原始总金额: 7392
===== 规则引擎结果 =====
应用规则:满100减10
应用规则:电子产品95折优惠 - iPhone
应用规则:图书9折优惠 - Java编程思想
应用规则:VIP客户9折优惠
应用规则:使用优惠券减50
优惠金额: 879.08
实际支付金额: 6512.92
这个案例展示了Drools规则引擎的核心功能:
- 规则定义:使用DRL语言定义业务规则
- 事实对象:Java对象作为Fact进行规则匹配
- 规则优先级:使用salience控制执行顺序
- 条件匹配:支持复杂条件判断和对象遍历
- 动作执行:规则执行时修改Fact对象状态
- Spring集成:与Spring Boot无缝集成
- 性能优化:合理使用状态会话和容器管理
通过Drools可以将业务规则从代码中解耦,实现规则的动态管理和热更新,非常适合复杂的业务决策场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播