阿里开源规则引擎QLExpress

news/2025/10/5 17:38:24/文章来源:https://www.cnblogs.com/xd502djj/p/19126767

阿里开源规则引擎QLExpress:彻底告别业务规则硬编码

动态脚本解析利器,让业务规则变得灵活可配置

在当今快速变化的业务环境中,如何高效灵活地处理频繁变动的业务规则成为了每个开发者面临的挑战。阿里巴巴开源的 QLExpress(Quick Language Express)正是为解决这一问题而生的动态脚本引擎,它通过将业务规则从程序代码中分离,极大地提升了系统的灵活性和可维护性。

什么是QLExpress?

QLExpress是阿里巴巴开源的一款轻量级、高性能的Java规则引擎和动态脚本执行框架,起源于阿里巴巴的电商业务,旨在解决业务规则、表达式、数学计算等动态脚本的解析问题。

与传统的硬编码方式相比,QLExpress将业务规则提取为外部可配置的脚本,使业务人员或配置人员能够在不修改代码的情况下调整业务逻辑,大大降低了系统维护成本和变更风险。

QLExpress的核心特性

QLExpress具有以下几个显著特点:

  • 线程安全:引擎运算过程中产生的临时变量都是threadlocal类型,确保并发场景下的线程安全性
  • 高效执行:支持脚本编译结果缓存,运行时临时变量创建采用缓冲池技术,性能与Groovy相当
  • 弱类型脚本语言:语法类似于Groovy和JavaScript,灵活度高,学习成本低
  • 安全控制:可预防死循环、高危系统API调用等安全问题
  • 轻量级:仅250KB的jar包,适合所有Java运行环境

QLExpress与其他规则引擎对比

在选择规则引擎时,了解各引擎的特点至关重要。以下是QLExpress与常见规则引擎的对比:

特性 Drools Aviator EasyRule QLExpress
语言 Drools规则语言(DRL) Aviator表达式语言 Java 弱类型脚本语言
性能 适用于复杂规则,可能较慢 高性能表达式求值 相对较高,适用于简单规则 高效执行,适用于业务规则和表达式计算
灵活性 非常灵活,支持动态修改规则 灵活,支持丰富运算符和函数 简单易用,适合非专业开发人员 灵活,支持业务规则、表达式和数学计算
应用场景 复杂的业务规则 简单表达式计算和规则 简单规则场景 业务规则、表达式、数学计算,适用于电商业务

从对比中可以看出,QLExpress在平衡性能、灵活性和学习成本方面表现出色,特别适合需要快速响应业务变化的场景。

快速入门:第一个QLExpress程序

下面通过一个简单的示例演示如何使用QLExpress。

1. 引入依赖

首先在Maven项目中引入QLExpress依赖:

<dependency><groupId>com.ql</groupId><artifactId>qlExpress</artifactId><version>3.3.0</version>
</dependency>

2. 基本使用示例

import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;public class QLExpressExample {public static void main(String[] args) {try {// 1. 创建表达式执行器ExpressRunner runner = new ExpressRunner();// 2. 创建上下文并设置变量DefaultContext<String, Object> context = new DefaultContext<>();context.put("amount", 1000);context.put("discount", 0.1);// 3. 执行脚本String expression = "amount * (1 - discount)";Object result = runner.execute(expression, context, null, true, false);// 4. 输出结果System.out.println("折扣后金额: " + result); // 输出:折扣后金额: 900.0} catch (Exception e) {e.printStackTrace();}}
}

这个简单的例子展示了QLExpress的基本使用流程:创建执行器→设置上下文→执行脚本→获取结果。

QLExpress的四要素理解

要深入掌握QLExpress,需要理解其四个核心要素:

1. 表达式执行器(ExpressRunner)

QLExpress的核心执行器,负责解析和执行脚本表达式。

2. 脚本表达式(Expression)

要执行的业务逻辑,可以是简单表达式或复杂的"类Json"脚本。

3. 上下文(Context)

脚本执行的环境,用于存储变量和共享数据。

4. 操作符(Operator)

QLExpress最基本的操作单元,支持算术运算符、比较运算符、逻辑运算符等。

QLExpress高级特性

1. Java对象操作

QLExpress支持直接操作Java对象,使脚本能够灵活访问和修改对象属性:

// 创建用户对象
User user = new User("John", 25);
context.put("user", user);// 在脚本中访问对象属性和方法
String expression1 = "user.getName()";
String expression2 = "user.getAge() + 5";
String expression3 = "user.age = 30";

2. 脚本中定义函数

QLExpress支持在脚本中定义函数,提高代码复用性:

String express = "function add(int a, int b){\n" +"   return a + b;\n" +"};\n" +"function sub(int a, int b){\n" +"   return a - b;\n" +"};\n" +"a = 10;\n" +"result = add(a, 4) + sub(a, 9);\n" +"return result;";

3. 扩展操作符和别名

QLExpress允许自定义操作符和别名,使脚本更符合业务语言习惯:

// 添加中文别名
runner.addOperatorWithAlias("如果", "if", null);
runner.addOperatorWithAlias("则", "then", null);
runner.addOperatorWithAlias("否则", "else", null);String express = "如果 (语文+数学+英语>270) 则 {return 1;} 否则 {return 0;}";

4. 宏定义

宏定义可以简化复杂表达式的重复书写:

expressRunner.addMacro("计算平均成绩", "(语文+数学+英语)/3.0");
expressRunner.addMacro("是否优秀", "计算平均成绩>90");Object result = expressRunner.execute("是否优秀", context, null, false, false);

实际应用案例:电商促销场景

QLExpress在电商促销活动中有着广泛应用,下面是一个典型的购物车优惠计算示例:

public double queryMinPromotionPrice(String cart, double shippingFee) {// 解析购物车数据JSONArray cartArray = JSONObject.parseArray(cart);double totalPrice = 0.0;for(int i = 0; i < cartArray.size(); i++) {String productCode = cartArray.getJSONObject(i).getString("productCode");double productPrice = cartArray.getJSONObject(i).getDoubleValue("price");// 查询商品参与的促销活动List<Promotion> promotionList = queryPromotion(productCode);// 根据促销规则计算优惠价格List<Double> nicePrices = querySinglePromotionPrice(promotionList, productPrice);double minPrice = Collections.min(nicePrices);totalPrice += minPrice;}return totalPrice;
}

在这种场景下,当促销规则变化时,只需修改规则配置即可,无需改动代码,极大提高了系统的灵活性和可维护性。

最佳实践与注意事项

1. 性能优化建议

  • 启用缓存:设置isCache=true可缓存编译结果,提升重复执行性能
  • 资源管理:及时清理不再使用的上下文和运行器,避免内存泄漏
  • 脚本优化:避免在脚本中编写过于复杂的逻辑,将复杂业务逻辑尽量放在Java代码中

2. 安全注意事项

  • 防止死循环:设置超时时间,避免脚本无限执行
  • API调用限制:限制脚本中对高危系统API的调用
  • 参数校验:对所有输入参数进行严格校验,防止注入攻击

3. 与Spring框架集成

QLExpress可以轻松与Spring框架集成,通过配置Bean的方式管理ExpressRunner实例:

@Configuration
public class QLExpressConfig {@Beanpublic ExpressRunner expressRunner() {ExpressRunner runner = new ExpressRunner();// 自定义配置return runner;}
}

总结

QLExpress作为阿里巴巴开源的轻量级规则引擎,通过将业务规则从代码中分离,为系统带来了前所未有的灵活性和可维护性。其线程安全、高效执行、灵活易用的特点,使其成为处理动态业务规则的理想选择。

无论是电商促销、金融风控还是实时定价系统,QLExpress都能提供强大的支持。通过本文的介绍,相信您已经对QLExpress有了全面的了解,现在就尝试在您的项目中应用它,体验告别硬编码的畅快感吧!

参考资料

  • https://github.com/alibaba/QLExpress
  • https://www.cnblogs.com/jingzh/p/18820020
  • https://blog.csdn.net/weixin_49426115/article/details/151287068

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/928530.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QOJ7411 Bitwise Xor

内部通道(jzyz P6035),与原题唯一不同在于一个也不选也算一种方案。 首先挖掘性质。将\(a_i\)从小到大排序后,\(a_i\oplus a_j\)的最小值一定在某一对相邻\(a_i\),即\(a_i\oplus a_{i+1}\)处取到。 简易证明:排过…

完整教程:SOC-ESP32S3部分:25-HTTP请求

完整教程:SOC-ESP32S3部分:25-HTTP请求pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "M…

为什么要采用“接口 - 抽象类 - 实现类”这种三层结构? - 浪矢

目录核心思想各层职责与优势第一层:接口 (Interface) - 负责“定义契约”,实现“解耦”第二层:抽象类 (Abstract Class) - 负责“封装通用”,实现“复用”第三层:实现类 (Implementation Class) - 负责“具体业务…

对外提供 AI 服务的风险:合规视角与 AI 安全围栏落地指南

对外提供人工智能服务,主要风险集中在提示词攻击与越权操控、不当内容输出与内容合规、敏感信息与个人信息泄露,以及算法合规、备案与可审计义务。自2023年《生成式人工智能服务管理暂行办法》实施后,企业需要把“数…

遵义市做网站设计公司苏州关键词优化排名推广

本文转载自&#xff1a;http://blog.sina.com.cn/s/blog_9a06890901014ol1.html PHP页面跳转一、header()函数 header函数中Location类型的标头是一种特殊的header调用&#xff0c;常用来实现页面跳转 注意&#xff1a;1、location和“:”号间不能有空格&#xff0c;否则不会跳…

网络安全工具与社区讨论月报

本文记录了r/netsec网络安全社区月度讨论帖,包含成员分享的常用安全工具如Burp Suite和Nuclei,以及社区规则和最新动态,为安全从业者提供实用参考。r/netsec 月度讨论与工具分享帖 社区介绍 /r/netsec 是一个由社区…

机器人运动未来与人机交互研究

本文探讨了机器人运动与人机长期交互的前沿研究,包括机器人意图信号系统、机器学习在机器人感知中的应用,以及大规模实验环境对机器人技术发展的重要性。机器人运动未来与人机交互研究 移动机器人正日益普及:它们在…

欧拉路径 欧拉图 小记

欧拉路径 & 欧拉图 小记 P7771 【模板】欧拉路径 欧拉路径:一个图中经过每条边恰好一次的路径,允许经过重复点。 欧拉回路:起点与终点相同的欧拉路径。 对于连通图,欧拉路径有如下判定:对于无向图,恰好有两个…

OI 笑传 #16

The Taste of Kindness指差す先はインナーワールド 1 ABC423F 终于会了不用二项式反演的做法。 我们把这种东西叫什么好呢?预处理容斥系数? 首先这题是不能一般容斥的,因为我们求解的不是并集,而是独立集。 哎哎独…

课后知识整理

课后知识整理Java方法动手动脑与实验问题全记录 静态导入实验 实验:随机数 Math.random() 局限性 (int)(Math.random()*6) 只能生成 0–5,而不能公平生成 1–6。 Random 带种子实验 实验:

cf296b

CF296B Yaroslav and Two Strings link 题意 给定两个由数字和 ? 组成的字符串 \(s,t\),将 ? 替换为数字。若 \(s,t\) 中有 \(s_i>w_i,s_j<w_j(1\leq i,j\leq n)\),则是一种合法的替换。求合法的方案数对 \(…

昆山做网站费用个人工作室怎么注册

这个教程会教您如何设计发光斑驳的字体特效&#xff0c;会教您运用PS滤镜和纹理图片&#xff0c;同时也诠释了如何运用笔刷和图层样式给最终的字体效果增添光感。来&#xff0c;先看看最终效果&#xff01;第一步&#xff1a;创建一个1024*768的新文档。前景色#532118&#xff…

云原生与DevOps融合实践:加速企业数字化转型的加速器 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

第一次使用Ttpora

MarkDown使用教学 两个井号创建二级标题 一个井号创建一级标题就是最上边的那个 字体 两边都加星号,字体就变成黑色了 两边都加星号,字体就变成黑色了 两边都加两个星号,字体就变成黑色了 两边加一个型号,变成斜体…

Apache反向代理

“apache2 网站静态文件” = /var/www/html/ Apache 本身就可以作为一个反向代理服务器来使用,通常是通过 mod_proxy 及其附加模块来实现。 下面是启用 Apache 反向代理的基本步骤: 1. 启用必要的模块 你需要启用以下…

原版 Sunshine+虚拟显示器实现熄屏串流

Sunshine 基地版 是一个很好的软件,自带了虚拟显示器,能够非常方便地实现熄屏串流,但有一个 bug,它会在串流结束后自动开启虚拟显示器的 HDR 功能:https://github.com/qiin2333/Sunshine-Foundation/issues/13 很…

一流的嘉兴网站建设最牛的视频网站建设

目录 第一章&#xff1a;Java Web基础知识1.介绍3.Java Web基本概念 4.常见面试问题第二章&#xff1a;Java Web核心概念和技术1.介绍3.Servlet和JSP4.Web安全5.常见面试问题 第三章&#xff1a;Java Web高级概念和技术1.介绍3.Spring框架4.安全性5.常见面试问题 第四章&#x…

2025国庆Day4

模拟赛 T1 简单做法: 发现本题所有运算全是加法 直接记录c,s之和 转移即可 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<…

苏宁易购网站建设目标成视频网址多少?

场景&#xff1a; 平台&#xff1a;win7 x64。显卡很差的电脑&#xff0c;使用ffmpeg录屏&#xff0c;鼠标闪烁的几乎看不到。录屏实现方法是使用ffmpeg&#xff0c;源采用的是gdigrab。 解决方法&#xff1a; 安装screen capture recorder安装ffmpeg&#xff0c;执行命令ff…

郑州网站开发公司电话网站在线优化

简介&#xff1a; 融合流量网关与微服务网关的下一代网关—云原生网关来啦&#xff01;优势满满&#xff01; 流量网关和微服务网关必须分开构建吗&#xff1f; 在容器技术和 K8s 主导的云原生时代&#xff0c;这个命题正浮现出新的答案。 更经济&#xff1a;将流量网关与微…