Aviator 规则引擎介绍

article/2025/10/23 23:54:34

先说结论: 规则简单:qlexpress或者avaitor;规则复杂:drools

最终选择是因为:足够轻量级,社区活跃度较好,最新jar包更新于22年4月

String expression = "a=='河北省'&&((b=='男人'||c>=30)||d=='黄')";// 编译表达式Expression compiledExp = AviatorEvaluator.compile(expression);Map<String, Object> env = new HashMap<>();env.put("a", "河北省");env.put("b", "男人");env.put("c",1);env.put("d","黄");// 执行表达式System.out.println( compiledExp.execute(env));

1、引入背景

1.1 需求背景及面临问题

系统分案时,需要针对规则进行解析:
示例:
((省份 = 河北省)并且((城市 = 张家口市)或者(城市 = 石家庄市))并且(服务类型 = 信用卡)并且((委托金额 > 1000)并且(委托金额 < 50000)))或者((省份 = 河北省)并且(城市 = 石家庄市)并且(服务类型 = 互联网))
解析条件:
(省份 = 河北省)并且(城市 = 张家口市)并且(服务类型 = 信用卡)并且(委托金额 > 1000)并且(委托金额 < 50000)
(省份 = 河北省)并且(城市 = 石家庄市)并且(服务类型 = 信用卡)并且(委托金额 > 1000)并且(委托金额 < 50000)
(省份 = 河北省)并且(城市 = 石家庄市)并且(服务类型 = 互联网)

1.2 面临问题

系统架构复杂
系统的可维护性和维护成本提高
系统的整合复杂
增加“硬代码”业务规则的成本和风险

2 为什么选用Aviator

2.1 简介

高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值
Aviator的设计目标是轻量级和高性能 ,相比于Groovy、JRuby的笨重,Aviator 非常小,加上依赖包也才450K,不算依赖包的话只有70K
其次,Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都 是通过解释的方式运行,而Aviator则是直接将表达式编译成Java字节码,交给 JVM去执行
简单来说,Aviator的定位是介于Groovy这样的重量级脚本语言和 IKExpression这样的轻量级表达式引擎之间。

2.2 特性介绍

支持大部分运算操作符,包括算术操作符、关系运算符、逻辑操作符、正则匹配操作符 、三元表达式 ,并且支持操作符的优先级和括号强制优先级,具体请看后面的操作符列表。
支持函数调用和自定义函数。
支持正则表达式匹配,类似Ruby、Perl的匹配语法,并且支持类Ruby的$digit指向匹配分组。自动类型转换,当执行操作的时候,会自动判断操作数类型并做相应转换,无法转换即抛异常。
支持传入变量,支持类似a.b.c的嵌套变量访问。
性能优秀。

2.3 整体结构

在这里插入图片描述

3 demo

3.1 引入pom

为啥选这个版本,因为这是按时间倒序的第二个稳定版本

<!-- https://mvnrepository.com/artifact/com.googlecode.aviator/aviator -->
<dependency><groupId>com.googlecode.aviator</groupId><artifactId>aviator</artifactId><version>5.3.0</version>
</dependency>

3.2 执行方式

execute():需要传递Map格式参数
exec():不需要传递Mappublic class Test {public static void main(String[] args) {// exec执行方式,无需传递Map格式String age = "18";System.out.println(AviatorEvaluator.exec("'His age is '+ age +'!'", age));// execute执行方式,需传递Map格式Map<String, Object> map = new HashMap<String, Object>();map.put("age", "18");System.out.println(AviatorEvaluator.execute("'His age is '+ age +'!'", map));}
}

3.3 支持函数


public class Test {public static void main(String[] args) {Map<String,Object> map = new HashMap<>();map.put("s1","123qwer");map.put("s2","123");System.out.println(AviatorEvaluator.execute("string.startsWith(s1,s2)",map));}
}

3.4 自定义函数

自定义函数要继承AbstractFunction类,重写目标方法。

public class Test {public static void main(String[] args) {// 注册自定义函数AviatorEvaluator.addFunction(new MultiplyFunction());// 方式1System.out.println(AviatorEvaluator.execute("multiply(12.23, -2.3)"));// 方式2Map<String, Object> params = new HashMap<>();params.put("a", 12.23);params.put("b", -2.3);System.out.println(AviatorEvaluator.execute("multiply(a, b)", params));}}class MultiplyFunction extends AbstractFunction{@Overridepublic AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {double num1 = FunctionUtils.getNumberValue(arg1, env).doubleValue();double num2 = FunctionUtils.getNumberValue(arg2, env).doubleValue();return new AviatorDouble(num1 * num2);}@Overridepublic String getName() {return "multiply";}}

3.5 运算符优先级

在这里插入图片描述

3.6 常量和变量

在这里插入图片描述

3.7 表达式Demo


public class Test {public static void main(String[] args) {String expression = "a+(b-c)>100";// 编译表达式Expression compiledExp = AviatorEvaluator.compile(expression);Map<String, Object> env = new HashMap<>();env.put("a", 100.3);env.put("b", 45);env.put("c", -199.100);// 执行表达式Boolean result = (Boolean) compiledExp.execute(env);System.out.println(result);}
}

3.8 数组和集合Demo

List和数组用list[0]和array[0],Map用map.date

public class Test {public static void main(String[] args) {final List<String> list = new ArrayList<>();list.add("hello");list.add(" world");final int[] array = new int[3];array[0] = 0;array[1] = 1;array[2] = 3;final Map<String, Date> map = new HashMap<>();map.put("date", new Date());Map<String, Object> env = new HashMap<>();env.put("list", list);env.put("array", array);env.put("map", map);System.out.println(AviatorEvaluator.execute("list[0]+':'+array[0]+':'+'today is '+map.date", env));}}

3.9 三元比较符

public class Test {public static void main(String[] args) {Map<String, Object> env = new HashMap<String, Object>();env.put("a", -5);String result = (String) AviatorEvaluator.execute("a>0? 'yes':'no'", env);System.out.println(result);}}

3.10 正则表达式匹配

public class Test {public static void main(String[] args) {String email = "hello2018@gmail.com";Map<String, Object> env = new HashMap<String, Object>();env.put("email", email);String username = (String) AviatorEvaluator.execute("email=~/([\\w0-8]+)@\\w+[\\.\\w+]+/ ? $1 : 'unknow' ", env);System.out.println(username);}
}

3.11 变量的语法糖衣

/*** CreateBy: haleyliu* CreateDate: 2018/12/25*/
public class Test {public static void main(String[] args) {User user = new User(1,"jack","18");Map<String, Object> env = new HashMap<>();env.put("user", user);String result = (String) AviatorEvaluator.execute(" '[user id='+ user.id + ',name='+user.name + ',age=' +user.age +']' ", env);System.out.println(result);}
}@Data
@AllArgsConstructor
@NoArgsConstructor
@NoArgsConstructor
@ToString
public class User {private int id;private String name;private String age;public User() {}}

3.12 nil对象[任何对象都比nil大除了nil本身]

AviatorEvaluator.execute("nil == nil");  //true AviatorEvaluator.execute(" 3> nil");    //true AviatorEvaluator.execute(" true!= nil");    //true AviatorEvaluator.execute(" ' '>nil ");  //true AviatorEvaluator.execute(" a==nil ");   //true,a is null
nil与String相加的时候,跟java一样显示为null

3.13 日期比较

public class Test {public static void main(String[] args) {Map<String, Object> env = new HashMap<String, Object>();final Date date = new Date();String dateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS").format(date);env.put("date", date);env.put("dateStr", dateStr);Boolean result = (Boolean) AviatorEvaluator.execute("date==dateStr",env);System.out.println(result);result = (Boolean) AviatorEvaluator.execute("date > '2009-12-20 00:00:00:00' ", env);System.out.println(result);result = (Boolean) AviatorEvaluator.execute("date < '2200-12-20 00:00:00:00' ", env);System.out.println(result);result = (Boolean) AviatorEvaluator.execute("date ==date ", env);System.out.println(result);}
}

4 语法手册

4.1 数据类型

Number类型:数字类型,支持两种类型,分别对应Java的Long和Double

任何整数都将被转换为Long

任何浮点数都将被转换为Double,包括用户传入的数值也是如此转换。

不支持科学计数法

支持十进制。如-1、100、2.3等。

整数也可以用十六进制表示,以 0x 或者 0X 开头的数字,比如 0xFF(255)、0xAB(171) 等等。

需要注意,整数相除的结果仍然是整数,比如例子中的 a/b 结果就是 0,遵循 java 的整数运算规则。

String类型: 字符串类型

单引号或者双引号括起来的文本串,如’hello world’

变量如果传入的是String或者Character也将转为String类型。

Bool类型:

常量true和false,表示真值和假值,与java的Boolean.TRUE和Boolean.False对应。

Pattern类型:

类似Ruby、perl的正则表达式,以//括起来的字符串,如//d+/

内部实现为java.util.Pattern。

变量类型:

与Java的变量命名规则相同,

变量的值由用户传入,如"a"、"b"等

nil类型: 常量nil,类似java中的null,

但是nil比较特殊,nil不仅可以参与==、!=的比较,也可以参与>、>=、<、<=的比较,

Aviator规定任何类型都n大于nil除了nil本身,nil==nil返回true。

用户传入的变量值如果为null,那么也将作为nil处理,nil打印为null。

4.2 算术运算符

支持常见的算术运算符,包括+ - / % 五个二元运算符和一元运算符"-“。
其中 - / %和一元的”-"仅能作用于Number类型。
"+"不仅能用于Number类型,还可以用于String的相加,或者字符串与其他对象的相加。
Aviator规定,任何类型与String相加,结果为String。

4.3 逻辑运算符

Avaitor的支持的逻辑运算符包括,一元否定运算符"!“,以及逻辑与的”&&“,逻辑或的”||"。逻辑运算符的操作数只能为Boolean。

4.4 关系运算符

Aviator支持的关系运算符包括"<" “<=” “>” “>=” 以及"==“和”!=" 。

&&和||都执行短路规则。

关系运算符可以作用于Number之间、String之间、Pattern之间、Boolean之间、变量之间以及其他类型与nil之间的关系比较,不同类型除了nil之外不能相互比较。

Aviator规定任何对象都比nil大除了nil之外。

4.5 匹配运算符

匹配运算符"=~"用于String和Pattern的匹配,它的左操作数必须为String,右操作数必须为Pattern。
匹配成功后,Pattern的分组将存于变量$num,num为分组索引。

4.6 三元运算符

两种模式
默认AviatorEvaluator以编译速度优先:

AviatorEvaluator.setOptimize(AviatorEvaluator.COMPILE);
你可以修改为运行速度优先,这会做更多的编译优化:

AviatorEvaluator.setOptimize(AviatorEvaluator.EVAL);


http://chatgpt.dhexx.cn/article/IxgRpcgq.shtml

相关文章

aviator实战

aviator规则引擎轻量、高性能可以帮我们解决很多配置规则的问题 官方文档参考&#xff1a;Aviator帮助文档 实战一把aviator&#xff0c;举个栗子 对年龄在40岁以内、职级大于等于3的“宋姓”销售人员发放提成&#xff0c; 提成计算公式“销售量 * 单件提成金额 * 10%” 代码…

aviator java,基于Aviator的规则引擎系统设计

项目里或多或少的都会有一些基于规则判断的代码&#xff0c;而往往这部分逻辑判断代码都写在项目里&#xff0c;改规则就得改代码&#xff0c;所以就很不方便&#xff0c;而且随着规则越多&#xff0c;代码越繁杂。 最近有时间&#xff0c;设计了一套基于Aviator的规则引擎系统…

Aviator源码:Aviator表达式引擎执行过程源码分析

目录 1.if执行脚本示例 2.源码分析 2.1 compile执行过程 2.1.1 CodeGenerator 2.1.2 ExpressionParser 2.1.3 if脚本ASM反编译结果 2.2 compiledExpression.execute执行过程 3.总结概述 由于Aviator支持的脚本语法较多&#xff0c;下面通过项目中使用较多的if语句来对a…

Aviator使用

“初步了解和使用Aviator” 1.Aviator简介 Aviator 是一个高性能&#xff0c;轻量级的java语言实现的表达式求值引擎&#xff0c;主要用于各种表达式的动态求值。 官方文档 github地址 支持数字、字符串、正则表达式、布尔值、正则表达式等基本类型&#xff0c;完整支持所有…

java aviator_Aviator 表达式求值引擎开源框架

简介 Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎&#xff0c;主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎&#xff0c;为什么还需要Avaitor呢&#xff1f; Aviator的设计目标是轻量级和高性能&#xff0c;相比于Groovy、JRuby…

java aviator_Aviator——让表达式飞起来

《飞行大亨》是我很喜欢的一部电影&#xff0c;不过这里我想介绍的是一个叫Aviator的开源的Java表达式求值器。 一、轮子的必要性 表达式的求值上&#xff0c;java的选择非常多&#xff0c;强大的如Groovy、JRuby&#xff0c;N年没维护的beanshell&#xff0c;包括javaeye上朋友…

Aviator

Aviator 简介 Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎&#xff0c;主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎&#xff0c;为什么还需要Avaitor呢&#xff1f; Aviator的设计目标是轻量级和高性能 &#xff0c;相比于Groo…

Aviator介绍

Aviator简介 Aviator是一个高性能、轻量级的 java 语言实现的表达式求值引擎, 主要用于各种表达式的动态求值。现在已经有很多开源可用的 java 表达式求值引擎,为什么还需要 Avaitor 呢? Aviator的设计目标是轻量级和高性能,相比于Groovy、JRuby的笨重, Aviator非常小, 加上…

西电计算机学院名誉院长,杨孟飞院士受聘为西电计科院名誉院长及讲席教授

西电新闻网讯(通讯员 陈龙)12月21日上午&#xff0c;西安电子科技大学计算机科学与技术学院名誉院长杨孟飞院士“华山学者”讲席教授及战略咨询委员会委员聘任仪式在北校区主楼Ⅱ区319会议室举行&#xff0c;校长杨宗凯、副校长王泉参加仪式。仪式由计科院执行院长崔江涛主持。…

北航计算机学院新闻,澳门理工学院代表团访问我校计算机学院

北航新闻网1月21日电(通讯员 盛浩)2019年1月16日&#xff0c;澳门理工学院副院长李雁莲教授、孙毓奇教授等一行三人到北航计算机学院就双方合作等事项进行交流。 座谈会由先进计算机应用技术教育部工程研究中心熊璋教授主持&#xff0c;计算机学院副院长胡春明副教授、中心李超…

【华人学者风采】陈晓峰 西安电子科技大学

【华人学者风采】陈晓峰&#xff0c;西安电子科技大学网络与信息安全学院副院长。研究方向包括公钥密码学、金融密码学、云计算安全、数据安全、区块链技术及应用、人工智能安全。曾获荣誉&#xff1a; 国家万人计划科技创新领军人才&#xff0c;教育部“青年长江学者” &#…

港科资讯 | 倪明选校长等出席江门“双碳”实验室揭牌暨项目签约仪式

12月7日&#xff0c;由香港科技大学&#xff08;广州&#xff09;&#xff08;筹&#xff09;和江门市政府发起共建的江门“双碳”实验室举行了揭牌暨项目签约仪式&#xff0c;江门双碳实验室正式启动成立。香港科技大学&#xff08;广州&#xff09;&#xff08;筹&#xff09…

莫队算法(普通莫队、带修莫队、树上莫队、不删除莫队)学习笔记【理解+套路/核心代码+例题及题解】

一、理解 我的理解就是巧妙的暴力&#xff0c;利用双指针以及分块思想&#xff0c;巧妙的移动双指针&#xff0c;时间复杂度可以达到O(NlogN)。 强推博客&#xff1a;写的又好又全。链接 二、套路 1、普通莫队 【1】核心代码 bool cmp(node a,node b){return belong[a.l]…

香港理工大学计算机系石杰明老师组招收全奖博士生、博士后

来源&#xff1a;AI求职 香港理工大学 香港理工大学位于中国香港特别行政区&#xff0c;QS 最新排名世界 66 位。计算机系&#xff08;Department of Computing&#xff09;USNews CS 排名 36&#xff0c;泰晤士 CS 排名 79。 石杰明博士课题组成员包括有 985/211 顶尖高校背景…

【调剂】华侨大学计算机学院计算机视觉与模式识别实验室钟必能课题组研究生招生...

点击文末的阅读原文或者公众号界面左下角的调剂信息或者公众号回复“调剂”是计算机/软件等专业的所有调剂信息集合&#xff0c;会一直更新的。 课题组主页&#xff1a;https://cst.hqu.edu.cn/info/1109/2001.htmLinkedin: https://www.linkedin.com/in/bineng-zhong-71a36674…

莫队算法思想

目录 莫队算法普通莫队方法&#xff1a;主要代码结构&#xff1a;例题&#xff1a;小B的询问例题&#xff1a;小Z的袜子奇偶化排序 带修改的莫队小结&#xff1a; 莫队算法 莫队算法是由前国家队莫涛提出的一种算法&#xff0c;主要应用在一类离线区间查询的问题中&#xff0c…

【华人学者风采】冯佳时 新加坡国立大学

【华人学者风采】冯佳时&#xff0c;新加坡国立大学ECE系助理教授。本科毕业于中国科学技术大学&#xff0c;硕士毕业于中国科学院自动化研究所&#xff0c;博士毕业于新加坡国立大学。研究兴趣包括大污染数据分析&#xff0c;在线和分布式鲁棒性学习及其在对象识别中的应用。 …

港科夜闻|央视网专访香港科大(广州)(筹)校长倪明选教授,谈香港科技大学在科研及知识转移方面成就...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、央视网专访香港科大(广州)(筹)校长倪明选教授&#xff0c;谈香港科技大学在科研及知识转移方面成就。香港科技大学(广州)(筹)校长倪明选教授接受央视网专访&#xff0c;谈香港科技大学在科研及知识转移方面取得的成就&am…

独家对话许诗军:数字化转型,最基本的是不去拒绝 |数字价值观察室(下)...

关注ITValue&#xff0c;看企业级最新鲜、最价值报道&#xff01; ▎本文摘自《云栖战略参考》&#xff0c;这本刊物由阿里云与钛媒体联合策划。目的是为了把各个行业先行者的技术探索、业务实践呈现出来&#xff0c;与思考同样问题的“数字先行者”共同探讨、碰撞&#xff0c;…

港科夜闻|香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏...

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科技大学(广州)(筹)校长倪明选教授在北京拜访国家教育部党组书记、部长怀进鹏。2021年11月1日&#xff0c;香港科技大学(广州)(筹)校长倪明选教授等一行在北京拜访国家教育部党组书记、部长怀进鹏。 2、深圳先进院与…