EasyRules案例

wen java案例 2

Easy Rules 案例详解

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

EasyRules案例


基础用法 - 学生成绩评级

场景

根据学生分数给出评级(优秀/良好/及格/不及格)。

代码实现

// 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 注入对象 业务上下文传递

使用建议

  1. 规则定义外部化:把规则放在 YAML 或 JSON 文件中,实现动态修改,无需重启系统
  2. 规则命名规范:清晰描述规则目的,便于维护
  3. 优先级控制:合理设置 priority 控制规则执行顺序
  4. 性能优化:对于高频查询,使用缓存或预编译规则

这些案例覆盖了 Easy Rules 的核心功能,可以根据实际业务需求进行扩展和组合。

抱歉,评论功能暂时关闭!