Easy Rules 案例详解
Easy Rules 是一个轻量级的 Java 规则引擎库,下面通过几个典型案例来展示它的用法。

基础用法 - 学生成绩评级
场景
根据学生分数给出评级(优秀/良好/及格/不及格)。
代码实现
// 1. 引入依赖 (Maven)
/*
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-rules-core</artifactId>
<version>4.1.0</version>
</dependency>
*/
import org.jeasy.rules.annotation.*;
// 2. 定义规则类
public class GradeRule {
@Condition
public boolean isExcellent(@Fact("score") int score) {
return score >= 90;
}
@Action
public void excellentAction(@Fact("score") int score) {
System.out.println("成绩优秀: " + score + "分");
}
@Priority
public int getPriority() {
return 1;
}
}
运行规则
import org.jeasy.rules.api.*;
import org.jeasy.rules.core.*;
public class Main {
public static void main(String[] args) {
// 创建规则
Rules rules = new Rules();
rules.register(new GradeRule());
// 创建事实
Facts facts = new Facts();
facts.put("score", 92);
// 创建规则引擎并触发
RulesEngine engine = new DefaultRulesEngine();
engine.fire(rules, facts);
}
}
输出结果:
成绩优秀: 92分
规则组合 - 订单折扣系统
场景
根据订单金额、用户等级来提供不同的折扣。
代码实现
import org.jeasy.rules.annotation.*;
import org.jeasy.rules.core.*;
import org.jeasy.rules.api.*;
// 规则1:VIP用户折扣
public class VipDiscountRule {
@Condition
public boolean isVip(@Fact("userLevel") String level) {
return "VIP".equals(level);
}
@Action
public void applyVipDiscount(@Fact("order") Order order) {
order.setDiscount(order.getDiscount() + 0.2);
System.out.println("VIP用户额外折扣20%");
}
@Priority
public int getPriority() {
return 1;
}
}
// 规则2:大金额订单折扣
public class LargeOrderDiscountRule {
@Condition
public boolean isLargeOrder(@Fact("order") Order order) {
return order.getAmount() > 1000;
}
@Action
public void applyLargeDiscount(@Fact("order") Order order) {
order.setDiscount(order.getDiscount() + 0.1);
System.out.println("大额订单额外折扣10%");
}
@Priority
public int getPriority() {
return 2;
}
}
// 订单类
class Order {
private double amount;
private double discount;
public Order(double amount) {
this.amount = amount;
this.discount = 0;
}
// getters/setters...
public double getAmount() { return amount; }
public double getDiscount() { return discount; }
public void setDiscount(double discount) { this.discount = discount; }
public double getFinalPrice() {
return amount * (1 - discount);
}
}
运行
public class Test {
public static void main(String[] args) {
// 创建订单
Order order = new Order(1500);
// 创建事实
Facts facts = new Facts();
facts.put("order", order);
facts.put("userLevel", "VIP");
// 注册规则
Rules rules = new Rules();
rules.register(new VipDiscountRule());
rules.register(new LargeOrderDiscountRule());
// 执行
RulesEngine engine = new DefaultRulesEngine();
engine.fire(rules, facts);
System.out.println("原价: 1500, 最终价格: " + order.getFinalPrice());
}
}
输出结果:
VIP用户额外折扣20%
大额订单额外折扣10%
原价: 1500, 最终价格: 1050.0
规则链 - 根据条件触发不同规则
场景
将规则组织成链式结构,根据条件判断是否进入下一个规则。
import org.jeasy.rules.api.*;
import org.jeasy.rules.mvel.MVELRuleFactory;
import org.jeasy.rules.support.reader.*;
import org.mvel2.ParserContext;
import java.io.StringReader;
public class RuleChainExample {
public static void main(String[] args) throws Exception {
// 使用 Yaml 定义规则
String yamlRule = """
name: "age-check"
description: "年龄校验规则"
priority: 1
condition: "age > 18"
actions:
- "System.out.println('成年人,可以办理业务');"
- "age = 20;"
""";
// 创建规则工厂
MVELRuleFactory ruleFactory = new MVELRuleFactory(
new YamlRuleDefinitionReader()
);
// 加载规则
Rule ageRule = ruleFactory.createRule(new StringReader(yamlRule));
// 创建第二个规则
String yamlRule2 = """
name: "school-check"
description: "学生检查"
priority: 2
condition: "age >= 20"
actions:
- "System.out.println('年龄符合学校要求');"
""";
Rule schoolRule = ruleFactory.createRule(new StringReader(yamlRule2));
// 组合规则
Rules rules = new Rules();
rules.register(ageRule);
rules.register(schoolRule);
// 创建事实
Facts facts = new Facts();
facts.put("age", 22);
// 执行
RulesEngine engine = new DefaultRulesEngine();
engine.fire(rules, facts);
}
}
复杂业务 - 优惠券计算系统
场景
多种优惠券叠加计算最佳组合。
import org.jeasy.rules.annotation.*;
import org.jeasy.rules.api.*;
import org.jeasy.rules.core.*;
import java.util.*;
// 优惠券规则
public class CouponRule {
@Condition
public boolean isCouponUsable(@Fact("coupon") Coupon coupon,
@Fact("order") Order order) {
return coupon.isActive() &&
order.getAmount() >= coupon.getMinAmount() &&
coupon.getEndDate().after(new Date());
}
@Action
public void applyCoupon(@Fact("coupon") Coupon coupon,
@Fact("order") Order order) {
if (coupon.getType() == CouponType.PERCENT) {
// 百分比优惠券
double discount = order.getAmount() * (coupon.getValue() / 100.0);
order.setDiscount(order.getDiscount() + discount);
} else {
// 固定金额优惠券
order.setDiscount(order.getDiscount() + coupon.getValue());
}
coupon.setUsed(true);
}
}
// 优惠券类
enum CouponType { PERCENT, FIXED }
class Coupon {
private String name;
private CouponType type;
private double value;
private double minAmount;
private Date startDate;
private Date endDate;
private boolean active = true;
private boolean used = false;
// getters/setters...
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public CouponType getType() { return type; }
public void setType(CouponType type) { this.type = type; }
public double getValue() { return value; }
public void setValue(double value) { this.value = value; }
public double getMinAmount() { return minAmount; }
public void setMinAmount(double minAmount) { this.minAmount = minAmount; }
public Date getStartDate() { return startDate; }
public void setStartDate(Date startDate) { this.startDate = startDate; }
public Date getEndDate() { return endDate; }
public void setEndDate(Date endDate) { this.endDate = endDate; }
public boolean isActive() { return active; }
public boolean isUsed() { return used; }
public void setUsed(boolean used) { this.used = used; }
}
运行示例
public class CouponTest {
public static void main(String[] args) {
// 创建订单
Order order = new Order(500);
// 创建优惠券列表
List<Coupon> coupons = Arrays.asList(
createCoupon("满100减20", CouponType.FIXED, 20, 100),
createCoupon("8折优惠", CouponType.PERCENT, 20, 50)
);
// 创建事实
Facts facts = new Facts();
facts.put("order", order);
// 对每个优惠券应用规则
RulesEngine engine = new DefaultRulesEngine();
for (Coupon coupon : coupons) {
facts.put("coupon", coupon);
Rules rules = new Rules();
rules.register(new CouponRule());
// 只执行一次
engine.fire(rules, facts);
}
System.out.println("最终优惠金额: " + order.getDiscount());
System.out.println("实际支付: " + order.getFinalPrice());
}
private static Coupon createCoupon(String name, CouponType type,
double value, double minAmount) {
Coupon coupon = new Coupon();
coupon.setName(name);
coupon.setType(type);
coupon.setValue(value);
coupon.setMinAmount(minAmount);
coupon.setStartDate(new Date(System.currentTimeMillis() - 86400000));
coupon.setEndDate(new Date(System.currentTimeMillis() + 86400000));
return coupon;
}
}
高级特性:组合规则 (Composite Rules)
import org.jeasy.rules.api.*;
import org.jeasy.rules.core.*;
import org.jeasy.rules.support.*;
public class CompositeRulesExample {
public static void main(String[] args) {
// 创建单元规则
Rule rule1 = new RuleBuilder()
.name("条件1")
.when(facts -> facts.get("value") > 10)
.then(facts -> System.out.println("值大于10"))
.build();
Rule rule2 = new RuleBuilder()
.name("条件2")
.when(facts -> facts.get("value") < 50)
.then(facts -> System.out.println("值小于50"))
.build();
Rule rule3 = new RuleBuilder()
.name("条件3")
.when(facts -> facts.get("value") % 2 == 0)
.then(facts -> System.out.println("值是偶数"))
.build();
// 创建组合规则:所有条件都满足才执行 (AND)
UnitRuleGroup andGroup = new UnitRuleGroup("AND组合", "所有条件满足才执行");
andGroup.addRule(rule1);
andGroup.addRule(rule2);
andGroup.addRule(rule3);
// 创建组合规则:任一条件满足就执行 (OR)
ActivationRuleGroup orGroup = new ActivationRuleGroup("OR组合", "任一条件满足就执行");
orGroup.addRule(rule1);
orGroup.addRule(rule2);
// 使用组合规则
Rules rules = new Rules();
rules.register(andGroup);
Facts facts = new Facts();
facts.put("value", 30); // 30 > 10, 30 < 50, 30 是偶数
RulesEngine engine = new DefaultRulesEngine();
engine.fire(rules, facts);
}
}
| 特性 | 说明 | 典型使用场景 |
|---|---|---|
| 注解方式 | @Condition, @Action, @Priority |
简单业务规则 |
| 规则链 | 通过 priority 控制执行顺序 | 审批流程、计算逻辑 |
| 组合规则 | UnitRuleGroup(AND), ActivationRuleGroup(OR) | 复杂条件判断 |
| YAML 规则 | 外部化规则定义,热替换 | 业务需求频繁变动 |
| 事实注入 | 使用 @Fact 注入对象 |
业务上下文传递 |
使用建议
- 规则定义外部化:把规则放在 YAML 或 JSON 文件中,实现动态修改,无需重启系统
- 规则命名规范:清晰描述规则目的,便于维护
- 优先级控制:合理设置 priority 控制规则执行顺序
- 性能优化:对于高频查询,使用缓存或预编译规则
这些案例覆盖了 Easy Rules 的核心功能,可以根据实际业务需求进行扩展和组合。