定义一个业务订单的场景,根据订单类型,执行对应的业务操作。假设,订单类型为两种:普通类型、折扣类型。
普通类型订单:打印日志处理
折扣类型订单:执行折扣计算方法
下面介绍一下不引入mysql和引入mysql两种方式,首先先写入共同的部分。
<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>
@Data
public class BizOrder {
/**
* 商品
*/
private String goods;
/**
* 售价
*/
private BigDecimal amount;
/**
* 订单类型 1、普通类型 2、折扣类型
*/
private Integer type;
/**
* 折扣
*/
private BigDecimal discount;
}
@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()));
}
}
}
@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
@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());
}
}
@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);
}
}
@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);
}
[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。
[
{
"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)"
]
}
]
}
]
@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()));
}
}
@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:Java规则引擎easy rules