Aviator是一个用于动态表达式求值的高性能、轻量级Java引擎。以下是一些关于Aviator引擎的重要特点和设计目标:
轻量级和高性能: Aviator的设计目标之一是轻量级和高性能。它的大小很小,加上依赖包也很小,这有助于将其轻松集成到各种Java应用程序中。与某些重量级的脚本语言(如Groovy)相比,Aviator非常紧凑,因此适用于对性能要求较高的应用程序。
编译执行方式: Aviator与许多其他表达式引擎的不同之处在于,它不是通过解释表达式来执行,而是将表达式编译成Java字节码,然后将其交给Java虚拟机(JVM)执行。这种编译执行方式通常比解释执行更快。
受限的语法: Aviator的语法是有限的,它并不是一门完整的编程语言,而只是专注于表达式求值的一小部分。这种受限的语法使其易于学习和使用。
支持运算操作符: Aviator支持大部分运算操作符,包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(=~)、三元表达式(?:)等。它还支持操作符的优先级和括号强制优先级。
自定义函数支持: Aviator允许用户定义自己的函数,这样您可以将自定义逻辑集成到表达式中,以满足特定的需求。
Aviator的实现思路与许多其他轻量级表达式求值器不同。它采用编译执行方式,将表达式直接编译成Java字节码,然后由Java虚拟机(JVM)执行。这种实现方式在性能上通常比解释执行更快。
其他轻量级表达式求值器通常采用解释执行方式,即通过分析和解释表达式字符串来执行计算。这使得它们更灵活,但也导致了性能开销较大。而Aviator的编译执行方式可以将表达式在执行前编译成字节码,这有助于提高性能,特别是对于需要频繁执行相同表达式的应用。
总的来说,Aviator的设计目标是提供一个介于重量级脚本语言(如Groovy)和轻量级表达式引擎(如IKExpression)之间的解决方案,它强调高性能和轻量级特性。这使得Aviator适用于那些需要快速、高效执行动态表达式求值的应用场景。
Aviator、IKExpression、QLExpress比较和建议
Aviator:
特点: 高性能:采用编译执行方式,将表达式编译成Java字节码,执行速度较快。轻量级:小巧的库,适用于需要高性能的应用。支持大部分运算操作符和自定义函数。语法相对受限,主要用于表达式求值。
使用建议: 当您需要在高性能环境中执行动态表达式,特别是需要频繁执行相同表达式的情况时,Aviator是一个不错的选择。如果您的主要需求是进行数学计算、条件检查或表达式求值,Aviator可以提供快速的执行。
IKExpression:
特点: 轻量级:IKExpression是一款轻量级的表达式引擎,适用于小型应用和嵌入式系统。
基于解释执行方式,相对较慢。支持常见的运算操作符和一些内置函数。语法相对简单,适合基本表达式求值。
使用建议:当您需要在轻量级Java应用或嵌入式系统中执行简单的动态表达式时,IKExpression是一个合适的选择。不适合需要高性能执行的大型应用程序或复杂的表达式。
QLExpress:
特点: 基于Java的表达式引擎,支持类似SQL的语法。较高的性能,使用JIT编译等技术进行优化。
支持条件检查、数据过滤和复杂计算。提供了类似SQL的语法,适合复杂表达式需求。
使用功建议:当您需要在Java应用程序中执行类似SQL的复杂动态表达式,或需要进行数据过滤和复杂计算时,QLExpress是一个很好的选择。适用于性能要求较高且需要执行复杂表达式的应用。
总体建议:
选择应取决于项目的具体需求、性能要求和规模。如果可能,可以根据具体情况尝试不同的引擎以找到最适合项目的解决方案。
<dependencies>
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<!-- <scope>test</scope>-->
</dependency>
</dependencies>
@Test
public void test1() {
//发送规则表达式
String expression = "(age > 35 && age < 75) && avgYear > 10000 && level == 1";
//编译表达式
Expression compileExp = AviatorEvaluator.compile(expression);
//设置变量
Map<String, Object> map = new HashMap<>();
map.put("age", 40);
map.put("level", 2);
map.put("avgYear", 20000);
//执行表达式
System.out.println(compileExp.execute(map));//结果: false
}
//表达式传值
@Test
public void test(){
//表达式传值
Map<String, Object> env = new HashMap<>();
env.put("name", "world");
String str = "'hello ' + name";
String r = (String) AviatorEvaluator.execute(str, env);
System.out.println(r);//hello world
}
@Test
public void test3(){
//算数表达式
Long sum = (Long) AviatorEvaluator.execute("1 + 2 + 3");
System.out.println(sum);//6
//逻辑表达式
boolean result = (boolean) AviatorEvaluator.execute("3 > 1");
System.out.println(result);//true
String r1 = (String) AviatorEvaluator.execute("100 > 80 ? 'yes' : 'no'");
System.out.println(r1);//yes
}
//函数调用
@Test
public void function() {
//函数调用
Long r2 = (Long) AviatorEvaluator.execute("string.length('hello')");
System.out.println(r2);//5
//调用自定义函数
//注册函数
AviatorEvaluator.addFunction(new CustomFunction());
//调用函数
System.out.println(AviatorEvaluator.execute("add(2,3)"));//5.0
//删除函数
//AviatorEvaluator.removeFunction("multi");
}
public class AviatorExampleTwo {
//规则可以保存在数据库中,mysql或者redis等等
Map<Integer, String> ruleMap = new HashMap<>();
public AviatorExampleTwo() {
//秒数计算公式
ruleMap.put(1, "hour * 3600 + minute * 60 + second");
//正方体体积计算公式
ruleMap.put(2, "height * width * length");
//判断一个人是不是资深顾客
ruleMap.put(3, "age >= 18 && sumConsume > 2000 && vip");
//资深顾客要求修改
ruleMap.put(4, "age > 10 && sumConsume >= 8000 && vip && avgYearConsume >= 1000");
//判断一个人的年龄是不是大于等于18岁
ruleMap.put(5, "age >= 18 ? 'yes' : 'no'");
}
public Object getResult(int ruleId, Object... args) {
String rule = ruleMap.get(ruleId);
return AviatorEvaluator.exec(rule, args);
}
public static void main(String[] args) {
AviatorExampleTwo aviatorExample = new AviatorExampleTwo();
//选择规则,传入规则所需要的参数
System.out.println("公式1:" + aviatorExample.getResult(1, 1, 1, 1));
System.out.println("公式2:" + aviatorExample.getResult(2, 3, 3, 3));
System.out.println("公式3:" + aviatorExample.getResult(3, 20, 3000, false));
System.out.println("公式4:" + aviatorExample.getResult(4, 23, 8000, true, 2000));
System.out.println("公式5:" + aviatorExample.getResult(5, 12));
}
}
public class CustomFunction extends AbstractFunction {
@Override
public String getName() {
return "add";
}
@Override
public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
Number left = FunctionUtils.getNumberValue(arg1, env);
Number right = FunctionUtils.getNumberValue(arg2, env);
return new AviatorDouble(left.doubleValue() + right.doubleValue());
}
}