news 2026/3/27 3:50:22

太强了!SpringBoot + QLExpress打造动态规则引擎!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
太强了!SpringBoot + QLExpress打造动态规则引擎!

作为一名后端开发,你是否遇到过这样的场景:

运营同学说:"双11活动规则临时调整,满300减60改成满200减50,能马上上线吗?"

产品经理说:"风控策略需要微调一下,这个规则能不能今晚就生效?"

老板说:"竞品降价了,我们的VIP折扣也要调整,最好现在就能改!"

每次遇到这种情况,我们都要:修改代码 → 重新打包 → 发布部署 → 重启服务。这个流程短则半小时,长则几个小时,错过最佳时机不说,还要承担发布风险。

今天,我们来聊聊如何用动态规则引擎解决这个痛点!

01

业务痛点:规则变更的"老大难"问题

传统方式的困境

// 硬编码,修改需要重新发布 if ("GOLD".equals(userLevel) && amount >= 100) { return amount * 0.8; }

在传统的业务系统中,业务规则通常硬编码在业务逻辑中:

// 传统的硬编码方式 public BigDecimal calculateVipDiscount(String userLevel, BigDecimal price) { if ("GOLD".equals(userLevel)) { return price.multiply(new BigDecimal("0.8")); // 8折 } else if ("SILVER".equals(userLevel)) { return price.multiply(new BigDecimal("0.9")); // 9折 } return price; // 无折扣 }

这种方式存在诸多问题:

  • 响应慢:规则变更需要完整的开发流程

  • 风险高:每次发布都可能影响整个系统

  • 成本大:需要开发、测试、运维多方配合

  • 不灵活:无法快速响应市场变化

真实的业务场景

电商行业:

• 每逢大促活动,优惠规则频繁调整

• A/B测试需要不同的定价策略

• 竞品价格变动需要快速跟进

金融行业:

• 风控模型需要根据市场情况实时调整

• 利率政策变化需要快速响应

• 审核规则需要根据业务发展动态优化

内容平台:

• 推荐算法需要不断优化

• 内容审核规则需要及时更新

• 用户等级体系需要灵活调整

02

解决方案:动态规则引擎

核心思路

动态规则引擎的本质是将业务规则与业务代码分离:

  • 业务代码:负责流程控制和数据处理

  • 业务规则:以脚本形式独立存储,运行时动态执行

技术选型

本演示DEMO我选择了以下技术栈:

  • 规则引擎:QLExpress - 阿里开源

  • 后端框架:Spring Boot - 快速开发

  • 前端技术:HTML5 + TailwindCSS

03

核心实现:手把手搭建动态规则引擎

  1. 项目结构设计

springboot-dynamic-rule/ ├── entity/ │ ├── RuleScript.java # 规则实体 │ ├── OrderProcessResult.java # 订单处理结果 │ └── RuleExecuteResponse.java # 规则执行响应 ├── service/ │ ├── DynamicRuleEngine.java # 规则引擎核心 │ └── OrderService.java # 业务服务 ├── controller/ │ ├── RuleController.java # 规则管理API │ └── OrderController.java # 业务API └── resources/ └── static/ ├── index.html # 规则管理页面 └── business.html # 业务演示页面
  1. 规则引擎核心实现

@Slf4j @Service public class DynamicRuleEngine { // 内存存储规则,实际项目可使用数据库 private final Map<String, RuleScript> ruleCache = new ConcurrentHashMap<>(); private final ExpressRunner expressRunner = new ExpressRunner(); @PostConstruct public void init() { initDefaultRules(); } private void initDefaultRules() { // VIP折扣规则 addRule(new RuleScript("vip_discount", "if (userLevel == \"GOLD\") { return price * 0.8; } " + "else if (userLevel == \"SILVER\") { return price * 0.9; } " + "else { return price; }", "VIP用户折扣规则")); // 满减活动规则 addRule(new RuleScript("full_reduction", "if (totalAmount >= 200) { return totalAmount - 50; } " + "else if (totalAmount >= 100) { return totalAmount - 20; } " + "else { return totalAmount; }", "满减活动规则")); } public RuleExecuteResponse executeRule(String ruleName, Map<String, Object> params) { try { RuleScript rule = ruleCache.get(ruleName); if (rule == null || !rule.isEnabled()) { return RuleExecuteResponse.error("规则不存在或已禁用: " + ruleName); } DefaultContext<String, Object> context = new DefaultContext<>(); if (params != null) { params.forEach(context::put); } Object result = expressRunner.execute(rule.getScript(), context, null, true, false); log.info("执行规则: {}, 结果: {}", ruleName, result); return RuleExecuteResponse.success(result); } catch (Exception e) { log.error("执行规则失败: {}", ruleName, e); return RuleExecuteResponse.error("执行失败: " + e.getMessage()); } } }
  1. 业务服务集成

@Service @RequiredArgsConstructor public class OrderService { private final DynamicRuleEngine ruleEngine; public OrderProcessResult processOrder(Order order) { List<OrderProcessResult.ProcessStep> steps = new ArrayList<>(); BigDecimal currentAmount = order.getOriginalAmount(); // 1. 应用VIP折扣规则 BigDecimal discountedAmount = applyVipDiscount(order, currentAmount, steps); // 2. 应用满减规则 BigDecimal finalAmount = applyFullReduction(order, discountedAmount, steps); // 3. 计算积分奖励 Integer points = calculatePoints(finalAmount, order); return new OrderProcessResult(/* 构建返回结果 */); } private BigDecimal applyVipDiscount(Order order, BigDecimal currentAmount, List<OrderProcessResult.ProcessStep> steps) { Map<String, Object> params = new HashMap<>(); params.put("userLevel", order.getUserLevel()); params.put("price", currentAmount); RuleExecuteResponse response = ruleEngine.executeRule("vip_discount", params); if (response.isSuccess()) { BigDecimal result = new BigDecimal(response.getResult().toString()); BigDecimal reduction = currentAmount.subtract(result); // 记录处理步骤 steps.add(new OrderProcessResult.ProcessStep( "VIP折扣", "根据用户等级 " + order.getUserLevel() + " 应用折扣", currentAmount, result, reduction, "vip_discount" )); return result; } return currentAmount; } }
  1. REST API接口

@RestController @RequestMapping("/api/rules") @RequiredArgsConstructor public class RuleController { private final DynamicRuleEngine dynamicRuleEngine; @GetMapping public ResponseEntity<List<RuleScript>> getAllRules() { return ResponseEntity.ok(dynamicRuleEngine.getAllRules()); } @PostMapping public ResponseEntity<String> addRule(@RequestBody RuleScript ruleScript) { try { dynamicRuleEngine.addRule(ruleScript); return ResponseEntity.ok("规则添加成功"); } catch (Exception e) { return ResponseEntity.badRequest().body("添加失败: " + e.getMessage()); } } @PutMapping("/{ruleName}") public ResponseEntity<String> updateRule(@PathVariable String ruleName, @RequestBody RuleScript ruleScript) { try { dynamicRuleEngine.updateRule(ruleName, ruleScript); return ResponseEntity.ok("规则更新成功"); } catch (Exception e) { return ResponseEntity.badRequest().body("更新失败: " + e.getMessage()); } } @PostMapping("/execute/{ruleName}") public ResponseEntity<RuleExecuteResponse> executeRule( @PathVariable String ruleName, @RequestBody Map<String, Object> params) { RuleExecuteResponse response = dynamicRuleEngine.executeRule(ruleName, params); return ResponseEntity.ok(response); } }

操作界面

为了方便大家快速直观的体验规则引擎,DEMO提供了一套简洁的操作界面,包含规则配置与业务场景模拟。

规则管理页面

主要功能:

  • 规则列表:展示所有规则及状态

  • 在线编辑:支持规则脚本的在线修改

  • 实时测试:规则修改后立即测试效果

  • 状态控制:一键启用/禁用规则

业务演示页面

  • 订单模拟器:输入订单信息,查看处理结果

  • 详细步骤:清晰展示每个规则的执行过程

  • 处理历史:记录历史处理结果

关键前端代码:

// 动态执行规则 async function executeRule(ruleName, params) { try { const response = await fetch(`/api/rules/execute/${ruleName}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(params) }); const result = await response.json(); if (result.success) { displayResult(`执行成功!结果: ${result.result}`); } else { displayResult(`执行失败: ${result.errorMessage}`); } } catch (error) { displayResult(`请求失败: ${error.message}`); } } // 渲染处理步骤 function displayProcessSteps(processSteps) { const stepsHtml = processSteps.map((step, index) => { const beforeAmount = parseFloat(step.beforeAmount); const afterAmount = parseFloat(step.afterAmount); const reduction = parseFloat(step.reduction); return ` <div class="process-step"> <div class="step-number">${index + 1}</div> <div class="step-content"> <h4>${step.stepName}</h4> <p>${step.description}</p> </div> <div class="step-result"> <div class="amount-change">¥${beforeAmount} → ¥${afterAmount}</div> <div class="reduction">节省 ¥${reduction.toFixed(2)}</div> </div> </div> `; }).join(''); document.getElementById('processingSteps').innerHTML = stepsHtml; }

04

应用场景实战

场景1:电商平台动态定价

需求:根据用户等级和订单金额,动态计算优惠价格

传统方式

动态规则方式

// 规则脚本,可随时修改 if (userLevel == "GOLD" && totalAmount >= 100) { return totalAmount * 0.8; } else if (userLevel == "SILVER" && totalAmount >= 50) { return totalAmount * 0.9; } else { return totalAmount; }

效果对比

  • 响应速度:从小时级降低到分钟级

  • 发布风险:从系统级降低到规则级

  • 操作门槛:从开发人员扩展到业务人员

场景2:风控策略实时调整

需求:根据实时风险情况,动态调整审核策略

规则示例:

// 风控评分规则 score = baseScore; if (userAge < 18) { score = score - 20; } if (creditLevel == "HIGH") { score = score + 30; } if (monthlyIncome > 10000) { score = score + 15; } return score >= 60 ? "PASS" : "REJECT";
// 双11活动规则 if (activityType == "DOUBLE11") { if (totalAmount >= 1000) { return totalAmount - 200; } else if (totalAmount >= 500) { return totalAmount - 80; } else if (totalAmount >= 200) { return totalAmount - 30; } } return totalAmount;

业务价值

  • 快速响应:市场风险变化时立即调整

  • 精细化控制:不同场景使用不同策略

  • A/B测试:同时运行多套策略进行对比

场景3:营销活动灵活配置

需求:支持复杂的营销活动规则

规则示例

运营效果

  • 活动预热:提前配置规则,定时生效

  • 实时调整:根据活动效果实时优化

  • 快速止损:发现问题立即回滚规则

05

总结

通过将业务规则从代码中剥离出来,我们实现了:

  • 业务敏捷:规则变更从小时级提升到分钟级

  • 系统稳定:减少了系统发布频次和风险

  • 团队协作:业务人员可以直接参与规则配置

  • 成本降低:减少了开发、测试、运维的工作量

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/14 8:35:35

基于单片机的智能油烟机(有完整资料)

资料查找方式&#xff1a;特纳斯电子&#xff08;电子校园网&#xff09;&#xff1a;搜索下面编号即可编号&#xff1a;CP-51-2021-050设计简介&#xff1a;本设计是基于单片机的智能油烟机系统&#xff0c;主要实现以下功能&#xff1a;可通过LCD1602显示烟雾浓度、温度、阈值…

作者头像 李华
网站建设 2026/3/21 16:51:08

CrossFormer 实现图像分类以及视觉任务的骨干网络替换 它使用交替的局部和全局注意力击...

CrossFormer 实现图像分类以及视觉任务的骨干网络替换 它使用交替的局部和全局注意力击败了 PVT 和 Swin。 全局注意力是在窗口维度上完成的&#xff0c;以降低复杂性&#xff0c;还具有跨尺度嵌入层&#xff0c;被证明是可以改进所有视觉转换器的通用骨干网络。 并设计了动态相…

作者头像 李华
网站建设 2026/3/26 6:51:04

基于单片机的心率脉搏设计

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录概要一、研究的主要内容光电传感器检测原理二、硬件设计说明3.1 总设计方案三、电路原理图四、结论概要 在我们现在的日常生活中脉搏心率测量仪器的使用已经越来越广泛了。为了使脉搏心率测量仪在简便性和精度方面有所提…

作者头像 李华
网站建设 2026/3/24 8:02:38

求求你们了,别再写满屏的 try catch 了!看如何更优雅地处理异常?

说明&#xff1a;本文讲得比较细&#xff0c;所以篇幅较长。请认真读完&#xff0c;希望读完后能对统一异常处理有一个清晰的认识。 01 背景 软件开发过程中&#xff0c;不可避免的是需要处理各种异常&#xff0c;就我自己来说&#xff0c;至少有一半以上的时间都是在处理各种…

作者头像 李华
网站建设 2026/3/21 20:11:29

基于Python的大学生就业信息推荐系统的设计与实现

前言在高等教育普及化背景下&#xff0c;大学生就业市场竞争日益激烈。传统就业信息获取方式存在信息过载、匹配度低、时效性差等问题&#xff0c;导致学生求职效率低下&#xff0c;企业招聘成本高昂。基于Python的大学生就业信息推荐系统通过整合多源就业数据&#xff0c;运用…

作者头像 李华