本文目录导读:

我为你整理一个完整的Java规则引擎实战案例,涵盖从基础到进阶的多种实现方式。
业务场景:电商订单折扣系统
- 根据用户等级、订单金额、商品类型等条件计算折扣
- 支持规则动态配置和热更新
技术方案选型
// 方案对比 1. Drools - 重型规则引擎,支持复杂规则 2. Easy Rules - 轻量级,适合简单场景 3. 自研规则引擎 - 灵活可控
案例实现
1 使用Easy Rules实现(推荐入门)
项目依赖:
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-core</artifactId>
<version>4.1.0</version>
</dependency>
业务模型:
// 订单实体类
public class Order {
private String userId;
private double amount; // 订单金额
private int userLevel; // 用户等级 1-普通 2-VIP 3-SVIP
private String productType; // 商品类型
private double discount; // 计算后的折扣
// 构造器、getter/setter省略
}
// 用户实体类
public class User {
private String userId;
private int level; // 用户等级
private boolean isNewUser; // 是否新用户
private int orderCount; // 累计订单数
}
规则定义:
import org.jeasy.rules.annotation.*;
@Rule(name = "VIP用户折扣规则", description = "VIP用户享受9折优惠")
public class VipDiscountRule {
@Condition
public boolean isVip(@Fact("user") User user) {
return user.getLevel() >= 2;
}
@Action
public void applyDiscount(@Fact("order") Order order) {
order.setDiscount(order.getDiscount() * 0.9);
System.out.println("VIP用户折扣已应用: 9折");
}
@Priority
public int getPriority() {
return 1; // 优先级,数字越小越先执行
}
}
@Rule(name = "满减规则", description = "订单满1000减100")
public class ThresholdDiscountRule {
@Condition
public boolean isOverThreshold(@Fact("order") Order order) {
return order.getAmount() >= 1000;
}
@Action
public void applyThresholdDiscount(@Fact("order") Order order) {
double discountedAmount = order.getAmount() - 100;
order.setAmount(discountedAmount);
System.out.println("满减规则已应用: 减100元");
}
@Priority
public int getPriority() {
return 2;
}
}
@Rule(name = "新用户优惠规则", description = "新用户首次购物9.5折")
public class NewUserDiscountRule {
@Condition
public boolean isNewUser(@Fact("user") User user) {
return user.isNewUser() && user.getOrderCount() == 0;
}
@Action
public void applyNewUserDiscount(@Fact("order") Order order) {
order.setDiscount(order.getDiscount() * 0.95);
System.out.println("新用户折扣已应用: 9.5折");
}
@Priority
public int getPriority() {
return 3;
}
}
规则引擎执行器:
import org.jeasy.rules.api.*;
import org.jeasy.rules.core.*;
import java.util.ArrayList;
import java.util.List;
public class DiscountRuleEngine {
private Rules rules;
private RulesEngine rulesEngine;
public DiscountRuleEngine() {
// 初始化规则引擎
rules = new Rules();
rulesEngine = new DefaultRulesEngine();
// 配置引擎参数
RulesEngineParameters parameters = new RulesEngineParameters()
.skipOnFirstAppliedRule(false) // 是否跳过后续规则
.skipOnFirstFailedRule(false); // 失败是否继续
rulesEngine = new DefaultRulesEngine(parameters);
// 注册默认规则
registerDefaultRules();
}
private void registerDefaultRules() {
rules.register(new VipDiscountRule());
rules.register(new ThresholdDiscountRule());
rules.register(new NewUserDiscountRule());
}
// 动态添加规则
public void addRule(Object rule) {
if (rule.getClass().isAnnotationPresent(Rule.class)) {
rules.register(rule);
}
}
// 移除规则
public void removeRule(Object rule) {
rules.unregister(rule);
}
// 执行规则
public Order executeRules(Order order, User user) {
Facts facts = new Facts();
facts.put("order", order);
facts.put("user", user);
// 初始化折扣为1(无折扣)
order.setDiscount(1.0);
rulesEngine.fire(rules, facts);
return order;
}
}
使用示例:
public class RuleEngineDemo {
public static void main(String[] args) {
// 创建规则引擎
DiscountRuleEngine engine = new DiscountRuleEngine();
// 创建测试用户
User vipUser = new User("U001", 2, false, 10);
User newUser = new User("U002", 1, true, 0);
User normalUser = new User("U003", 1, false, 5);
// 创建订单
Order order1 = new Order("O001", 1500, "electronics", 1.0);
Order order2 = new Order("O002", 800, "clothing", 1.0);
Order order3 = new Order("O003", 2000, "books", 1.0);
// 执行规则计算
Order result1 = engine.executeRules(order1, vipUser);
System.out.println("VIP用户大额订单最终金额: " + result1.getAmount() * result1.getDiscount());
Order result2 = engine.executeRules(order2, newUser);
System.out.println("新用户订单最终金额: " + result2.getAmount() * result2.getDiscount());
// 动态添加规则
engine.addRule(new SpecialEventRule()); // 节假日特殊折扣
Order result3 = engine.executeRules(order3, normalUser);
}
}
2 自研规则引擎(更灵活)
// 规则接口定义
public interface BusinessRule {
boolean evaluate(OrderContext context);
OrderContext execute(OrderContext context);
int getPriority();
String getRuleName();
}
// 上下文对象
public class OrderContext {
private Order order;
private User user;
private Map<String, Object> attributes = new HashMap<>();
private List<String> appliedRules = new ArrayList<>();
// 添加已应用规则记录
public void addAppliedRule(String ruleName) {
appliedRules.add(ruleName);
}
// getter/setter省略
}
// 具体规则实现
public class VipUserRule implements BusinessRule {
@Override
public boolean evaluate(OrderContext context) {
User user = context.getUser();
return user.getLevel() >= 2;
}
@Override
public OrderContext execute(OrderContext context) {
Order order = context.getOrder();
double newDiscount = order.getDiscount() * 0.9;
order.setDiscount(newDiscount);
context.addAppliedRule("VIP用户折扣");
return context;
}
@Override
public int getPriority() {
return 1;
}
@Override
public String getRuleName() {
return "vip_discount";
}
}
// 规则引擎核心
public class CustomRuleEngine {
private List<BusinessRule> rules = new ArrayList<>();
// 规则排序
public void addRule(BusinessRule rule) {
rules.add(rule);
rules.sort(Comparator.comparingInt(BusinessRule::getPriority));
}
// 执行所有规则
public Order execute(Order order, User user) {
OrderContext context = new OrderContext();
context.setOrder(order);
context.setUser(user);
order.setDiscount(1.0);
for (BusinessRule rule : rules) {
if (rule.evaluate(context)) {
context = rule.execute(context);
System.out.println("执行规则: " + rule.getRuleName() + ", 当前折扣: " +
order.getDiscount() * 100 + "%");
}
}
return order;
}
// 从配置文件加载规则
public void loadRulesFromConfig(String configPath) {
// 通过反射或配置加载规则
// 支持规则热更新
}
}
// XML配置规则示例
/*
<rules>
<rule name="vip" class="com.example.rules.VipUserRule" enabled="true"/>
<rule name="threshold" class="com.example.rules.ThresholdRule" enabled="true"/>
</rules>
*/
3 规则管理界面(Spring Boot集成)
@RestController
@RequestMapping("/api/rules")
public class RuleController {
private final DiscountRuleEngine ruleEngine;
@Autowired
public RuleController(DiscountRuleEngine ruleEngine) {
this.ruleEngine = ruleEngine;
}
// 查看所有规则
@GetMapping
public List<RuleInfo> getAllRules() {
// 返回规则信息列表
}
// 添加新规则
@PostMapping
public ResponseEntity<String> addRule(@RequestBody RuleDefinition ruleDef) {
try {
// 动态创建规则实例
Object rule = createRuleFromDefinition(ruleDef);
ruleEngine.addRule(rule);
return ResponseEntity.ok("规则添加成功");
} catch (Exception e) {
return ResponseEntity.badRequest().body("规则添加失败: " + e.getMessage());
}
}
// 更新规则
@PutMapping("/{ruleId}")
public ResponseEntity<String> updateRule(@PathVariable String ruleId,
@RequestBody RuleDefinition ruleDef) {
// 更新规则逻辑
}
// 删除规则
@DeleteMapping("/{ruleId}")
public ResponseEntity<String> deleteRule(@PathVariable String ruleId) {
// 删除规则逻辑
}
// 规则排序
@PostMapping("/reorder")
public ResponseEntity<String> reorderRules(@RequestBody List<String> ruleOrder) {
// 调整规则优先级
}
// 模拟测试规则
@PostMapping("/test")
public ResponseEntity<Order> testRules(@RequestBody TestRequest request) {
Order order = new Order();
// 填充order和user信息
Order result = ruleEngine.executeRules(order, request.getUser());
return ResponseEntity.ok(result);
}
}
// 规则定义DTO
public class RuleDefinition {
private String name; // 规则名称
private String condition; // 条件表达式
private List<String> actions; // 执行动作
private int priority; // 优先级
private boolean enabled; // 是否启用
// getter/setter省略
}
最佳实践建议
1 性能优化
// 规则缓存
@Service
public class RuleCache {
private Cache<String, List<BusinessRule>> ruleCache;
public void invalidateCache(String userId) {
// 用户规则变化时清除缓存
}
public List<BusinessRule> getCachedRules(String userId) {
// 优先从缓存获取
return ruleCache.get(userId, key -> loadRulesFromDB(key));
}
}
2 调试和监控
// 规则执行日志
@Aspect
@Component
public class RuleExecutionLogger {
@Around("@annotation(LogRuleExecution)")
public Object logExecution(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long duration = System.currentTimeMillis() - start;
// 记录规则执行时间和结果
log.info("规则执行耗时: {}ms, 结果: {}", duration, result);
return result;
}
}
3 规则版本管理
public class RuleVersion {
private String ruleId;
private int version;
private String content;
private boolean active;
private Date deployTime;
// 支持规则灰度发布
public boolean shouldDeploy(String userId) {
// 基于userId的hash决定是否启用新版本
int hash = Math.abs(userId.hashCode());
return hash % 100 < trafficPercentage;
}
}
生产环境注意事项
- 规则数量限制:单个业务场景建议不超过20条规则
- 规则优先级管理:明确规则执行顺序,避免冲突
- 超时控制:每个规则执行时间建议在100ms以内
- 幂等性:确保规则执行结果可重复,不影响业务数据
- 审计日志:记录规则决策路径,便于问题排查
- 回滚机制:支持规则快速回滚,降低变更风险
这个案例涵盖了Java规则引擎的主流实现方式,实际项目中选择方案时,根据业务复杂度、团队技术栈、维护成本等因素综合权衡,对于简单场景,自研或Easy Rules更轻量;复杂场景,Drools等重型引擎更适合。