
























核心痛点:业务规则高频变更与系统稳定性之间的矛盾
想象一个电商促销场景:
// 传统硬编码方式(噩梦开始...)
public BigDecimal calculateDiscount(Order order) {
BigDecimal discount = BigDecimal.ZERO;
if (order.getTotalAmount().compareTo(new BigDecimal("100")) >= 0) {
discount = discount.add(new BigDecimal("10"));
}
if (order.getUser().isVip()) {
discount = discount.add(new BigDecimal("5"));
}
当规则变成:"非VIP用户满200减30,VIP用户满150减40,且周二全场额外95折"时,代码将陷入维护地狱!
规则引擎通过分离规则逻辑解决这个问题:
下面给大家分享5种常用的规则引擎,希望对你会有所帮助。
// 规则文件 discount.drl
rule "VIP用户满100减20"
when
$user: User(level == "VIP")
$order: Order(amount > 100)
then
$order.addDiscount(20);
end
KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("discountSession");
kSession.insert(user);
kSession.insert(order);
kSession.fireAllRules();
优点:
缺点:
适合:不差钱的大厂,规则复杂度高的场景
官网:https://github.com/j-easy/easy-rules
@Rule(name = "雨天打折规则", description = "下雨天全场9折")
public class RainDiscountRule {
@Condition
public boolean when(@Fact("weather") String weather) {
return "rainy".equals(weather);
}
@Action
public void then(@Fact("order") Order order) {
order.setDiscount(0.9);
}
}
RulesEngineParameters params = new RulesEngineParameters()
.skipOnFirstAppliedRule(true);
优点:
缺点:
适合:中小项目快速落地,开发人员不足时
官网:https://github.com/alibaba/QLExpress
ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<>();
context.put("user", user);
context.put("order", order);
String express = "if (user.level == 'VIP') { order.discount = 0.85; }";
runner.execute(express, context, null, true, false);
// 1. 函数扩展
runner.addFunction("计算税费", new Operator() {
@Override
public Object execute(Object[] list) {
return (Double)list[0] * 0.06;
}
});
优点:
缺点:
适合:需要频繁修改规则的业务(如运营活动)
官网:https://github.com/killme2008/aviatorscript
// Aviator 表达式
Expression exp = AviatorEvaluator.compile("user.age > 18 && order.amount > 100");
exp.execute(map);
| 引擎 | 耗时 |
|---|---|
| Aviator | 220ms |
| Groovy | 1850ms |
// 开启编译缓存(默认开启)
AviatorEvaluator.getInstance().useLRUExpressionCache(1000);
// 字节码生成模式(JDK8+)
AviatorEvaluator.setOption(Options.ASM, true);
优点:
缺点:
适合:对性能有极致要求的计算场景
<chain name="orderProcess">
<then value="checkStock,checkCredit"/>
LiteflowResponse response = FlowExecutor.execute2Resp("orderProcess", order, User.class);
if (response.isSuccess()) {
System.out.println("流程执行成功");
} else {
System.out.println("失败原因:" + response.getCause());
}
优点:
缺点:
适合:需要灵活编排的复杂业务流

| 引擎 | 耗时 | 内存占用 | 特点 |
|---|---|---|---|
| Drools | 420ms | 高 | 功能全面 |
| Easy Rules | 38ms | 低 | 轻量易用 |
| QLExpress | 65ms | 中 | 阿里系脚本引擎 |
| Aviator | 28ms | 极低 | 高性能表达式 |
| LiteFlow | 120ms | 中 | 流程编排专家 |

// 设置无状态会话(避免内存积累)
KieSession session = kContainer.newStatelessKieSession();
// 禁用危险方法
runner.addFunctionOfServiceMethod("exit", System.class, "exit", null, null);
// Drools冲突处理策略
KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
config.setProperty("drools.sequential", "true");
曾有人问我:“规则引擎会不会让程序员失业?” 我的回答是:“工具永远淘汰不了思考者,只会淘汰手工作坊”。
真正的高手,不是写更多代码,而是用更优雅的方式解决问题。
技术选型没有最好的,只有最合适的。
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。
本文收录于我的技术网站:http://www.susan.net.cn
免责声明:本内容来自平台创作者,博客园系信息发布平台,仅提供信息存储空间服务。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。