太强了!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 TailwindCSS03核心实现手把手搭建动态规则引擎项目结构设计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 # 业务演示页面规则引擎核心实现Slf4j Service public class DynamicRuleEngine { // 内存存储规则实际项目可使用数据库 private final MapString, 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, MapString, Object params) { try { RuleScript rule ruleCache.get(ruleName); if (rule null || !rule.isEnabled()) { return RuleExecuteResponse.error(规则不存在或已禁用: ruleName); } DefaultContextString, 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()); } } }业务服务集成Service RequiredArgsConstructor public class OrderService { private final DynamicRuleEngine ruleEngine; public OrderProcessResult processOrder(Order order) { ListOrderProcessResult.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, ListOrderProcessResult.ProcessStep steps) { MapString, 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; } }REST API接口RestController RequestMapping(/api/rules) RequiredArgsConstructor public class RuleController { private final DynamicRuleEngine dynamicRuleEngine; GetMapping public ResponseEntityListRuleScript getAllRules() { return ResponseEntity.ok(dynamicRuleEngine.getAllRules()); } PostMapping public ResponseEntityString addRule(RequestBody RuleScript ruleScript) { try { dynamicRuleEngine.addRule(ruleScript); return ResponseEntity.ok(规则添加成功); } catch (Exception e) { return ResponseEntity.badRequest().body(添加失败: e.getMessage()); } } PutMapping(/{ruleName}) public ResponseEntityString 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 ResponseEntityRuleExecuteResponse executeRule( PathVariable String ruleName, RequestBody MapString, 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 classprocess-step div classstep-number${index 1}/div div classstep-content h4${step.stepName}/h4 p${step.description}/p /div div classstep-result div classamount-change¥${beforeAmount} → ¥${afterAmount}/div div classreduction节省 ¥${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总结通过将业务规则从代码中剥离出来我们实现了业务敏捷规则变更从小时级提升到分钟级系统稳定减少了系统发布频次和风险团队协作业务人员可以直接参与规则配置成本降低减少了开发、测试、运维的工作量

相关新闻

Spring的自定义注解与处理器

Spring的自定义注解与处理器

1. 自定义注解的定义 自定义注解是 Java 中的一种元数据标记,允许在代码中添加自定义信息,并能通过反射机制进行处理。我们首先定义一个自定义注解,然后在 Spring 中使用该注解来标识需要处理的类或方法。 示例:定义一个简单的自…

2026/7/3 15:11:05 阅读更多 →
日化产品想贴牌?源头厂家直供,成本降一半

日化产品想贴牌?源头厂家直供,成本降一半

想要打造属于自己的洗发水、洗衣液、面膜或者洗手液品牌吗?贴牌生产(OEM)确实是一条最为快捷的路径。但许多刚开始涉足这个领域的新手,在第一步就遇到了麻烦:他们找不到真正的源头厂家,反而被贸易商一层又一层地加价&…

2026/7/3 15:11:07 阅读更多 →
总有机碳(TOC)分析仪原理

总有机碳(TOC)分析仪原理

总有机碳(TOC)分析仪原理 总有机碳(TOC)分析仪原理 在当今的化学、生物和环境科学研究领域,总有机碳(TOC)分析仪已成为不可或缺的实验设备。它通过精确测量水样中的有机碳含量,为制…

2026/7/5 18:07:54 阅读更多 →

最新新闻

笨阶乘C++解法详解(力扣1006)

笨阶乘C++解法详解(力扣1006)

问题解析:LeetCode 1006 “笨阶乘”要求对正整数 N 按递减顺序依次使用乘 *、除 /、加 、减 - 四个运算符循环计算,即 clumsy(N) N * (N-1) / (N-2) (N-3) - (N-4) * (N-5) / (N-6) ...,需返回计算结果。核心在于处理运算符优先级&#xf…

2026/7/6 8:13:24 阅读更多 →
我们打工人用好 WorkBuddy 这 5 个实用技能,轻松工作提效

我们打工人用好 WorkBuddy 这 5 个实用技能,轻松工作提效

大家好,我是赛博李同学。腾讯的 WorkBuddy 功能进化的非常之快,俨然它已经成为我日常办公小助手了,真正的生产力工具!今天就分享5个我天天在用的技能。没什么高深的东西,就是些实打实能帮你把时间抠出来的小活儿。一、…

2026/7/6 8:11:23 阅读更多 →
借助生成式 AI 和压缩算法,仅用 500 字节构建世界地图!

借助生成式 AI 和压缩算法,仅用 500 字节构建世界地图!

【导语:2026 年 6 月 28 日消息,有人曾在 JS1k 竞赛中用不到 1000 字节构建世界地图,如今借助生成式 AI 和压缩算法,成功将地图数据压缩至不到 500 字节,引发关注。】从 1000 字节到挑战 500 字节10 多年前&#xff0c…

2026/7/6 8:11:23 阅读更多 →
C语言typedef的用法详解

C语言typedef的用法详解

前言:先用人话搞懂核心概念1. typedef 到底是干嘛的?typedef 是 C 语言关键字,作用:给已存在的数据类型起别名(绰号),不会创造新类型,只是给原有类型换一个好写、好理解的名字。把它…

2026/7/6 8:09:23 阅读更多 →
LangChain学习及应用(超详细)

LangChain学习及应用(超详细)

1. 引言:为什么需要 LangChain? 在人工智能,特别是大语言模型(LLM)飞速发展的今天,我们拥有了像 GPT、Claude、文心一言等强大的通用模型。然而,将这些模型直接应用到复杂的业务场景中&#xff…

2026/7/6 8:01:19 阅读更多 →
基于SSM实现的网上书城系统 基于SSM的宾馆信息管理系统 基于SSM实现的社团管理系统 基于SSM的超市进销存管理系统 基于SSM的在校生职业走向调查分析系统 基于SSM实现的员工管理系统

基于SSM实现的网上书城系统 基于SSM的宾馆信息管理系统 基于SSM实现的社团管理系统 基于SSM的超市进销存管理系统 基于SSM的在校生职业走向调查分析系统 基于SSM实现的员工管理系统

基于springbootvue的在线问卷调查管理系统 基于ssm的鲜花销售系统 基于ssm的外卖点餐订餐管理系统 基于springboot的个人博客系统 基于SSM的房屋租赁管理系统 项目合集 提取码: 32y6 更多资料汇总 提取码: dk3h

2026/7/6 7:57:17 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻