规则引擎easy-rules初步学习之使用案例(四)

案例

定义一个业务订单的场景,根据订单类型,执行对应的业务操作。假设,订单类型为两种:普通类型、折扣类型。

普通类型订单:打印日志处理
折扣类型订单:执行折扣计算方法
下面介绍一下不引入mysql和引入mysql两种方式,首先先写入共同的部分。

1. maven依赖

<dependency>
      <groupId>org.jeasy</groupId>
      <artifactId>easy-rules-core</artifactId>
      <version>4.0.0</version>
    </dependency>
    <dependency>
      <groupId>org.jeasy</groupId>
      <artifactId>easy-rules-mvel</artifactId>
      <version>4.0.0</version>
    </dependency>
    <dependency>
      <groupId>org.jeasy</groupId>
      <artifactId>easy-rules-spel</artifactId>
      <version>4.0.0</version>
    </dependency>

2.订单对象po

@Data
public class BizOrder {

    /**
     * 商品
     */
    private String goods;

    /**
     * 售价
     */
    private BigDecimal amount;

    /**
     * 订单类型 1、普通类型 2、折扣类型
     */
    private Integer type;

    /**
     * 折扣
     */
    private BigDecimal discount;
}

3.折扣计算方法

@Component
@Slf4j
@Service
public class OrderService {
    /**
     * 折扣处理方法
     * @param param 参数
     */
    public static void doDiscountAction(Object param) {
        //可通过 instanceof 操作符来判断对象的具体类型
        if (param instanceof BizOrder) {
            BizOrder order = ((BizOrder) param);
            //Java.math.BigDecimal.multiply()方法,通过此BigDecimal相乘的值
            //order.getAmount().multiply(order.getDiscount())售价*折扣价
            log.error("商品goods:{},折后amount:{}", order.getGoods(), order.getAmount().multiply(order.getDiscount()));
        }
    }
}

不引入mysql

基于表达式

  1. 创建测试文档
@Test
  public void steamTest() throws Exception {
    //定义普通商品,商品1
    BizOrder order1=new BizOrder();
      order1.setGoods("商品1");
      order1.setAmount(BigDecimal.valueOf(200));
      order1.setType(1);
      order1.setDiscount(BigDecimal.valueOf(0.7));
    //定义折扣商品,商品2
//    BizOrder order2=new BizOrder();
//      order2.setGoods("商品2");
//      order2.setAmount(BigDecimal.valueOf(200));
//      order2.setType(2);
//      order2.setDiscount(BigDecimal.valueOf(0.7));

    //定义事实数据
    Facts facts = new Facts();
    facts.put("type", order1.getType());
    //组合规则,它触发第一个适用规则,并忽略组中的其他规则(XOR逻辑)
    //ActivationRuleGroup activationRuleGroup = new ActivationRuleGroup("order_type_rule","订单类型规则");
    //普通类型
    Rule ordinaryRule = new RuleBuilder()
            .name("ordinary_order_rule")
            .description("普通订单类型")
            .when(vo -> vo.get("type").equals(1))
            .then(vo -> log.info("这是一个普通订单"))
            .priority(0)
            .build();
    //activationRuleGroup.addRule(ordinaryRule);
    //折扣类型
    Rule discountRule = new RuleBuilder()
            .name("discount_order_rule")
            .description("折扣订单类型")
            .when(vo -> vo.get("type").equals(2))
            .priority(1)
            .then(vo -> {
              log.info("这是一个折扣订单");
              //执行其他逻辑
              OrderService.doDiscountAction(order1);
            })
            .build();
    //activationRuleGroup.addRule(discountRule);
    //注册
    Rules rules = new Rules();
    //rules.register(activationRuleGroup);
    rules.register(ordinaryRule);
    rules.register(discountRule);
    //启动点火
    RulesEngine rulesEngine = new DefaultRulesEngine();
    rulesEngine.fire(rules, facts);

  }

注解
在本案例中,实现触发第一个适用规则,并忽略组中的其他规则,可以使用组合规则ActivationRuleGroup ,也可以给规则设置排序priority,因为DefaultRulesEngine根据规则的自然顺序(默认为优先级)应用规则,所以执行到适用规则,也不继续往下走了。
2. 运行结果展示
商品为普通商品时:

BizOrder order1=new BizOrder();
order1.setGoods(“商品1”);
order1.setAmount(BigDecimal.valueOf(200));
order1.setType(1);
order1.setDiscount(BigDecimal.valueOf(0.7));

11:09:22.398 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
11:09:22.403 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
11:09:22.403 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'ordinary_order_rule', description = '普通订单类型', priority = '0'}
11:09:22.405 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'discount_order_rule', description = '折扣订单类型', priority = '1'}
11:09:22.405 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
11:09:22.405 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact{name='type', value=1}
11:09:22.405 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
11:09:22.408 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'ordinary_order_rule' triggered
11:09:22.409 [main] INFO com.rule.easyrule.EasyRulesTest - 这是一个普通订单
11:09:22.409 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'ordinary_order_rule' performed successfully
11:09:22.410 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'discount_order_rule' has been evaluated to false, it has not been executed

商品为折扣商品时

BizOrder order2=new BizOrder();
order2.setGoods(“商品2”);
order2.setAmount(BigDecimal.valueOf(200));
order2.setType(2);
order2.setDiscount(BigDecimal.valueOf(0.7));

11:22:29.564 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
11:22:29.568 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Registered rules:
11:22:29.568 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule { name = 'order_type_rule', description = '订单类型规则', priority = '2147483646'}
11:22:29.570 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Known facts:
11:22:29.570 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Fact{name='type', value=2}
11:22:29.570 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rules evaluation started
11:22:29.573 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'order_type_rule' triggered
11:22:29.575 [main] INFO com.rule.easyrule.EasyRulesTest - 这是一个折扣订单
11:22:29.575 [main] ERROR com.rule.easyrule.service.OrderService - 商品goods:商品2,折后amount:140.0
11:22:29.576 [main] DEBUG org.jeasy.rules.core.DefaultRulesEngine - Rule 'order_type_rule' performed successfully

基于注解

  1. 普通类型订单
@Rule(name = "ordinary_order_rule", description = "普通订单类型", priority = 1)
@Slf4j
public class OrdinaryOrderRule {

    @Condition
    public boolean when(@Fact("order") BizOrder order) {
        return Objects.equals(order.getType(), 1);
    }

    @Action
    public void action(@Fact("order") BizOrder order) {
        log.info("这是一个普通订单,商品goods:{}", order.getGoods());
    }
}
  1. 折扣类型订单
@Rule(name = "discount_order_rule", description = "折扣订单类型",priority =2)
@Slf4j
public class DiscountOrderRule {

    @Condition
    public boolean when(@Fact("order") BizOrder order) {
        return Objects.equals(order.getType(),2);
    }

    @Action(order = 1)
    public void action(@Fact("order")BizOrder order) {
        log.info("这是一个折扣订单,商品goods:{}",order.getGoods());
    }

    @Action(order = 2)
    public void action2(@Fact("order")BizOrder order) {
        //调用其他业务处理
        OrderService.doDiscountAction(order);
    }
}
  1. 接口处理
@PostMapping("/annotation")
    @SneakyThrows
    public void annotationTest(@RequestBody BizOrder order) {
        //定义数据
        Facts facts = new Facts();
        facts.put("order", order);
        ActivationRuleGroup activationRuleGroup = new ActivationRuleGroup("order_type_rule", "订单类型规则");
        activationRuleGroup.addRule(new OrdinaryOrderRule());
        activationRuleGroup.addRule(new DiscountOrderRule());
        //注册
        Rules rules = new Rules();
        rules.register(activationRuleGroup);
        //启动点火
        RulesEngine rulesEngine = new DefaultRulesEngine();
        rulesEngine.fire(rules, facts);
    }
  1. 运行及结果展示
    规则引擎easy-rules初步学习之使用案例(四)_第1张图片
[2022-04-02 11:56:30.335] [http-nio-8089-exec-1] [INFO ] [a.c.c.C.[Tomcat].[localhost].[/rule]:173 ] - Initializing Spring DispatcherServlet 'dispatcherServlet'
[2022-04-02 11:56:30.415] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:139 ] - Engine parameters { skipOnFirstAppliedRule = false, skipOnFirstNonTriggeredRule = false, skipOnFirstFailedRule = false, priorityThreshold = 2147483647 }
[2022-04-02 11:56:30.416] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:143 ] - Registered rules:
[2022-04-02 11:56:30.416] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:145 ] - Rule { name = 'order_type_rule', description = '订单类型规则', priority = '2147483646'}
[2022-04-02 11:56:30.417] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:151 ] - Known facts:
[2022-04-02 11:56:30.418] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:153 ] - Fact{name='order', value=BizOrder(goods=商品, amount=200, type=2, discount=0.7)}
[2022-04-02 11:56:30.418] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:82  ] - Rules evaluation started
[2022-04-02 11:56:30.419] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:108 ] - Rule 'order_type_rule' triggered
[2022-04-02 11:56:30.420] [http-nio-8089-exec-1] [INFO ] [le.easyrule.config.DiscountOrderRule:24  ] - 这是一个折扣订单,商品goods:商品
[2022-04-02 11:56:30.421] [http-nio-8089-exec-1] [ERROR] [m.rule.easyrule.service.OrderService:21  ] - 商品goods:商品,折后amount:140.0
[2022-04-02 11:56:30.423] [http-nio-8089-exec-1] [DEBUG] [.jeasy.rules.core.DefaultRulesEngine:113 ] - Rule 'order_type_rule' performed successfully

基于配置文件

可以是json(本文),也可以是yml,当然也可以结合Apollo。

  1. 定义json文件,biz_order_rule.json
[
  {
    "name":"order_type_rule",
    "description":"订单类型规则引擎",
    "priority":1,
    "compositeRuleType":"ActivationRuleGroup",
    "composingRules":[
      {
        "name":"ordinary_order_rule",
        "description":"普通订单类型",
        "condition":"param.getType().equals(1)",
        "priority":1,
        "actions":[
          "System.out.println(\"这是一个普通订单\")"
        ]
      },
      {
        "name":"discount_order_rule",
        "description":"折扣类型规则",
        "condition":"param.getType().equals(2)",
        "priority":2,
        "actions":[
          "OrderService.doDiscountAction(param)"
        ]
      }
    ]
  }
]
  1. 构建rules配置
@Component
public class ConfigRules {/**
   * 构建rules配置
   */
  public Rules fetchConfigRules() throws Exception {
    //JSON 表达式
    MVELRuleFactory ruleFactory = new MVELRuleFactory(new JsonRuleDefinitionReader());
    return ruleFactory.createRules(new FileReader(
      Objects.requireNonNull(SpringBootApplication.class.getClassLoader().getResource("biz_order_rule.json"))
      .getFile()));
  }
}
  1. API逻辑处理
 @AuthIgnore
  @OperationLog(value = "easy rules 配置文件测试")
  @PostMapping("/json")
  @SneakyThrows
  public ResultVo<?> jsonTest(@RequestBody BizOrder order) {
    //定义数据
    Facts facts = new Facts();
    facts.put("param", order);
    facts.put("OrderService",OrderService.class);
    //读取配置
    Rules rules = configRules.fetchConfigRules();
    BizRule<BizOrder> rule = new BizRule<>();
    //注册
    rules.register(rule);
    //启动点火
    RulesEngine rulesEngine = new DefaultRulesEngine();
    rulesEngine.fire(rules, facts);
    return ResultVo.success();
  }

引入mysql

下一篇在写
学习资料:
不引入mysql:Java规则引擎easy rules

你可能感兴趣的:(#,easy-rules,java,spring)