Aviator表达式引擎

目录

一、快速介绍

(一)Aviator

(二)Aviator、IKExpression、QLExpress比较和建议

二、基本应用使用手册

1.执行表达式

2.使用变量

3.exec 方法

4.调用函数

调用内置函数

调用字符串函数

调用自定义函数

5.编译表达式

6.访问数组和集合

7.三元操作符

8.正则表达式匹配

9.变量的语法糖

10.nil 对象

11.日期比较

12.大数计算和精度

13.两种运行模式

14.调试信息

参考文章


干货分享,感谢您的阅读!

一、快速介绍

(一)Aviator

Aviator是一个用于动态表达式求值的高性能、轻量级Java引擎。以下是一些关于Aviator引擎的重要特点和设计目标:

  1. 轻量级和高性能: Aviator的设计目标之一是轻量级和高性能。它的大小很小,加上依赖包也很小,这有助于将其轻松集成到各种Java应用程序中。与某些重量级的脚本语言(如Groovy)相比,Aviator非常紧凑,因此适用于对性能要求较高的应用程序。

  2. 编译执行方式: Aviator与许多其他表达式引擎的不同之处在于,它不是通过解释表达式来执行,而是将表达式编译成Java字节码,然后将其交给Java虚拟机(JVM)执行。这种编译执行方式通常比解释执行更快。

  3. 受限的语法: Aviator的语法是有限的,它并不是一门完整的编程语言,而只是专注于表达式求值的一小部分。这种受限的语法使其易于学习和使用。

  4. 支持运算操作符: Aviator支持大部分运算操作符,包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(=~)、三元表达式(?:)等。它还支持操作符的优先级和括号强制优先级。

  5. 自定义函数支持: Aviator允许用户定义自己的函数,这样您可以将自定义逻辑集成到表达式中,以满足特定的需求。

Aviator的实现思路与许多其他轻量级表达式求值器不同。它采用编译执行方式,将表达式直接编译成Java字节码,然后由Java虚拟机(JVM)执行。这种实现方式在性能上通常比解释执行更快。

其他轻量级表达式求值器通常采用解释执行方式,即通过分析和解释表达式字符串来执行计算。这使得它们更灵活,但也导致了性能开销较大。而Aviator的编译执行方式可以将表达式在执行前编译成字节码,这有助于提高性能,特别是对于需要频繁执行相同表达式的应用。

总的来说,Aviator的设计目标是提供一个介于重量级脚本语言(如Groovy)和轻量级表达式引擎(如IKExpression)之间的解决方案,它强调高性能和轻量级特性。这使得Aviator适用于那些需要快速、高效执行动态表达式求值的应用场景。

(二)Aviator、IKExpression、QLExpress比较和建议

Aviator、IKExpression 和 QLExpress 都是用于在Java应用程序中执行动态表达式求值的库,但它们具有不同的特点和适用场景。以下是对它们的比较和一些建议:

引擎特点使用建议
Aviator

高性能:采用编译执行方式,将表达式编译成Java字节码,执行速度较快。

轻量级:小巧的库,适用于需要高性能的应用。

支持大部分运算操作符和自定义函数。

语法相对受限,主要用于表达式求值。

当您需要在高性能环境中执行动态表达式,特别是需要频繁执行相同表达式的情况时,Aviator是一个不错的选择。

如果您的主要需求是进行数学计算、条件检查或表达式求值,Aviator可以提供快速的执行。

IKExpression

轻量级:IKExpression是一款轻量级的表达式引擎,适用于小型应用和嵌入式系统。

基于解释执行方式,相对较慢。

支持常见的运算操作符和一些内置函数。

语法相对简单,适合基本表达式求值。

当您需要在轻量级Java应用或嵌入式系统中执行简单的动态表达式时,IKExpression是一个合适的选择。

不适合需要高性能执行的大型应用程序或复杂的表达式。

QLExpress

基于Java的表达式引擎,支持类似SQL的语法。

较高的性能,使用JIT编译等技术进行优化。

支持条件检查、数据过滤和复杂计算。

提供了类似SQL的语法,适合复杂表达式需求。

当您需要在Java应用程序中执行类似SQL的复杂动态表达式,或需要进行数据过滤和复杂计算时,QLExpress是一个很好的选择。

适用于性能要求较高且需要执行复杂表达式的应用。

总体建议:

  • 如果需要高性能的轻量级表达式引擎,Aviator是一个不错的选择。
  • 如果需要在小型或嵌入式应用中执行简单的表达式,IKExpression可能更适合。
  • 对于需要执行复杂表达式和条件检查的应用,QLExpress是一个强大的工具。

选择应取决于项目的具体需求、性能要求和规模。如果可能,可以根据具体情况尝试不同的引擎以找到最适合项目的解决方案。

二、基本应用使用手册

前置依赖如下:

        <dependency>
            <groupId>com.googlecode.aviator</groupId>
            <artifactId>aviator</artifactId>
            <version>5.3.3</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>20030211.134440</version>
        </dependency>

1.执行表达式

Aviator表达式引擎的使用通常通过com.googlecode.aviator.AviatorEvaluator入口类来处理。以下是一个最简单的示例,演示如何使用Aviator来执行一个计算1+2+3的表达式:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

/**
 * @program: zyfboot-javabasic
 * @description: Aviator举例
 * @author: zhangyanfeng
 * @create: 2023-10-20 23:25
 **/
public class AviatorExample {
    public static void main(String[] args) {
        // 创建 Aviator 表达式
        String expressionString = "1 + 2 + 3";
        Expression expression = AviatorEvaluator.getInstance().compile(expressionString);

        // 执行表达式并获取结果
        Long result = (Long) expression.execute();

        // 输出结果
        System.out.println("Result: " + result);
    }
}

Aviator的数值类型支持Long和Double,对于整数和浮点数,它们分别被映射为Long和Double。所以,对于表达式"1 + 2 + 3",打印的结果应该是6,如果需要执行更复杂的表达式,只需根据需求在表达式字符串中包括运算符、操作数和括号,Aviator将根据数学运算规则来计算结果,如下:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

/**
 * @program: zyfboot-javabasic
 * @description: 复杂表达式计算
 * @author: zhangyanfeng
 * @create: 2023-10-21 00:48
 **/
public class ComplexAviatorExpressions {
    public static void main(String[] args) {
        // 创建 Aviator 表达式
        String expressionString = "((5 + 3) * 2) / (4 - 1)";

        Expression expression = AviatorEvaluator.getInstance().compile(expressionString);

        // 执行表达式并获取结果
        Number result = (Number) expression.execute();

        // 输出结果
        System.out.println("Result: " + result); // 6.0
    }
}

创建一个包含括号的复杂数学表达式,涉及加法、减法、乘法和除法。Aviator表达式引擎可以正确处理这样的混合运算,根据括号来确保正确的优先级和计算顺序。执行该表达式会得到正确的结果,这里是6.0。

2.使用变量

在Aviator中使用变量是非常常见的,它允许您在表达式中引用不同的值。首先,需要定义要在表达式中使用的变量,变量通常存储在一个Map中,其中键是变量名,值是变量的值。当使用Aviator表达式引擎时,通常将定义变量、创建表达式和评估表达式放在一起。下面是一个示例,演示了如何定义变量、创建表达式和评估表达式的完整代码:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 使用变量
 * @author: zhangyanfeng
 * @create: 2023-10-21 01:01
 **/
public class AviatorVariableExample {
    public static void main(String[] args) {
        // 定义变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("x", 10);
        variables.put("y", 5);
        variables.put("name", "Alice");

        // 创建 Aviator 表达式
        String expressionString = "x > y ? name + ' says: Hello!' : name + ' says: Hi!'";
        Expression expression = AviatorEvaluator.getInstance().compile(expressionString);

        // 评估表达式并获取结果
        Object result = expression.execute(variables);

        // 输出结果
        System.out.println("Result: " + result); // 输出 Result: Alice says: Hello!
    }
}

3.exec 方法

Aviator表达式引擎的exec方法用于执行表达式,并返回结果。它通常在需要执行多个表达式或在不同上下文中多次执行表达式时使用。以下是有关如何使用exec方法的详细讲解和示例:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: exec 方法
 * @author: zhangyanfeng
 * @create: 2023-10-21 01:12
 **/
public class AviatorExecMethodExample {
    public static void main(String[] args) {
        // 创建 Aviator 表达式
        String expressionString = "x + y";

        // 编译表达式
        Expression expression = AviatorEvaluator.getInstance().compile(expressionString);

        // 定义变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("x", 10);
        variables.put("y", 5);

        // 第一次执行表达式
        Object result1 = expression.exec(variables);
        System.out.println("Result 1: " + result1); // 输出 Result 1: 15

        // 修改变量值
        variables.put("x", 20);
        variables.put("y", 8);

        // 第二次执行表达式
        Object result2 = expression.exec(variables);
        System.out.println("Result 2: " + result2); // 输出 Result 2: 28
    }
}

exec方法允许多次执行同一个表达式,每次在不同的上下文或不同的变量值下执行,以获得不同的结果。这对于需要重复执行相同表达式的情况非常有用,避免了多次编译相同的表达式,提高了性能。

注意,在Aviator 5.0及之后的版本中,exec方法已被移除,因此不再可用。如果使用的是Aviator的5.0或更新版本,应该使用execute方法来执行表达式,如之前的示例中所示。

4.调用函数

在Aviator中,您可以调用内置函数和自定义函数来扩展表达式的功能。

调用内置函数

Aviator内置了许多数学函数、字符串函数和其他常见函数,可以直接在表达式中使用。例如,调用abs函数计算绝对值:

String expressionString = "math.abs(-5)";

调用字符串函数

Aviator支持字符串操作,可以调用字符串函数来处理字符串。例如:

string.contains("test", string.substring('hello', 1, 2))

以上两种写个代码验证如下:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

/**
 * @program: zyfboot-javabasic
 * @description: 轻松调用内置函数和字符串函数
 * @author: zhangyanfeng
 * @create: 2023-10-21 01:23
 **/
public class AviatorBuiltInFunctionExample {
    public static void main(String[] args) {
        // 调用内置函数
        Number absResult = (Number) AviatorEvaluator.execute("math.abs(-5)");
        System.out.println("Absolute Value: " + absResult); // 输出 Absolute Value: 5.0

        // 5
        System.out.println(AviatorEvaluator.execute("string.length('hello')"));
        //通过string.substring('hello', 1, 2)获取字符串'e', 然后通过函数string.contains判断e是否在'test'中。可以看到, 函数可以嵌套调用。
        System.out.println(AviatorEvaluator.execute("string.contains(\"test\", string.substring('hello', 1, 2))"));
    }
}

这里我们常用的内置函数主要有如下:

函数名称

说明

sysdate()

返回当前日期对象 java.util.Date

rand()

返回一个介于 0-1 的随机数,double 类型

print([out],obj)

打印对象,如果指定 out,向 out 打印, 否则输出到控制台

println([out],obj)

与 print 类似,但是在输出后换行

now()

返回 System.currentTimeMillis

long(v)

将值的类型转为 long

double(v)

将值的类型转为 double

str(v)

将值的类型转为 string

date_to_string(date,format)

将 Date 对象转化化特定格式的字符串,2.1.1 新增

string_to_date(source,format)

将特定格式的字符串转化为 Date 对 象,2.1.1 新增

string.contains(s1,s2)

判断 s1 是否包含 s2,返回 Boolean

string.length(s)

求字符串长度,返回 Long

string.startsWith(s1,s2)

s1 是否以 s2 开始,返回 Boolean

string.endsWith(s1,s2)

s1 是否以 s2 结尾,返回 Boolean

string.substring(s,begin[,end])

截取字符串 s,从 begin 到 end,如果忽略 end 的话,将从 begin 到结尾,与 java.util.String.substring 一样。

string.indexOf(s1,s2)

java 中的 s1.indexOf(s2),求 s2 在 s1 中 的起始索引位置,如果不存在为-1

string.split(target,regex,[limit])

Java 里的 String.split 方法一致,2.1.1 新增函数

string.join(seq,seperator)

将集合 seq 里的元素以 seperator 为间隔 连接起来形成字符串,2.1.1 新增函数

string.replace_first(s,regex,replacement)

Java 里的 String.replaceFirst 方法, 2.1.1 新增

string.replace_all(s,regex,replacement)

Java 里的 String.replaceAll 方法 , 2.1.1 新增

math.abs(d)

求 d 的绝对值

math.sqrt(d)

求 d 的平方根

math.pow(d1,d2)

求 d1 的 d2 次方

math.log(d)

求 d 的自然对数

math.log10(d)

求 d 以 10 为底的对数

math.sin(d)

正弦函数

math.cos(d)

余弦函数

math.tan(d)

正切函数

map(seq,fun)

将函数 fun 作用到集合 seq 每个元素上, 返回新元素组成的集合

filter(seq,predicate)

将谓词 predicate 作用在集合的每个元素 上,返回谓词为 true 的元素组成的集合

count(seq)

返回集合大小

include(seq,element)

判断 element 是否在集合 seq 中,返回 boolean 值

sort(seq)

排序集合,仅对数组和 List 有效,返回排 序后的新集合

reduce(seq,fun,init)

fun 接收两个参数,第一个是集合元素, 第二个是累积的函数,本函数用于将 fun 作用在集合每个元素和初始值上面,返回 最终的 init 值

seq.eq(value)

返回一个谓词,用来判断传入的参数是否跟 value 相等,用于 filter 函数,如filter(seq,seq.eq(3)) 过滤返回等于3 的元素组成的集合

seq.neq(value)

与 seq.eq 类似,返回判断不等于的谓词

seq.gt(value)

返回判断大于 value 的谓词

seq.ge(value)

返回判断大于等于 value 的谓词

seq.lt(value)

返回判断小于 value 的谓词

seq.le(value)

返回判断小于等于 value 的谓词

seq.nil()

返回判断是否为 nil 的谓词

seq.exists()

返回判断不为 nil 的谓词

调用自定义函数

可以注册自定义函数以扩展Aviator的功能。首先,定义自定义函数类并实现AviatorFunction接口。然后,将函数注册到Aviator中,并在表达式中调用它。以下是一个示例:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDouble;
import com.googlecode.aviator.runtime.type.AviatorFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;

import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 自定义函数类
 * @author: zhangyanfeng
 * @create: 2023-10-21 15:03
 **/
public class MultiplyFunction implements AviatorFunction {
    @Override
    public String getName() {
        return "multiply";
    }

    @Override
    public AviatorObject call(Map<String, Object> map) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject) {
        return null;
    }

    @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());
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17, AviatorObject aviatorObject18) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17, AviatorObject aviatorObject18, AviatorObject aviatorObject19) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17, AviatorObject aviatorObject18, AviatorObject aviatorObject19, AviatorObject... aviatorObjects) {
        return null;
    }

    @Override
    public void run() {

    }

    @Override
    public AviatorObject call() throws Exception {
        return null;
    }
}

首先注册了一个名为multiply的自定义函数,并在表达式中调用它。自定义函数实现了AviatorFunction接口的call方法,根据传入的参数执行操作。然后,我们编译并执行表达式以获取结果。

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

/**
 * @program: zyfboot-javabasic
 * @description: 示例自定义函数
 * @author: zhangyanfeng
 * @create: 2023-10-21 15:20
 **/
public class AviatorCustomFunctionExample {
    public static void main(String[] args) {
        // 定义自定义函数并添加到 Aviator
        AviatorEvaluator.addFunction(new MultiplyFunction());

        // 定义表达式
        String expression = "multiply(3, 4)";

        try {
            // 解析并计算表达式
            Object result = AviatorEvaluator.execute(expression);
            System.out.println("Result: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Aviator表达式引擎提供了丰富的内置函数和自定义函数的支持,这使得它非常适用于各种计算和处理需求。根据需求可以注册更多自定义函数以满足特定的业务逻辑。

5.编译表达式

通过compile方法可以将表达式编译成Expression的中间对象, 当要执行表达式的时候传入env并调用Expression的execute方法即可。 表达式中使用了括号来强制优先级, 这个例子还使用了>用于比较数值大小, 比较运算符!=、==、>、>=、<、<=不仅可以用于数值, 也可以用于String、Pattern、Boolean等等, 甚至是任何用户传入的两个都实现了java.lang.Comparable接口的对象之间。列举运算符的多种情况验证如下:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 使用和比较运算符的多种情况
 * @author: zhangyanfeng
 * @create: 2023-10-21 15:43
 **/
public class AviatorOperatorExample {
    public static void main(String[] args) {
        // 编译表达式
        Expression compiledExp = AviatorEvaluator.compile("a - (b - c) > 100 && s1 == s2 && i1 >= i2");

        Map<String, Object> env = new HashMap<String, Object>();
        env.put("a", 100.3);
        env.put("b", 45);
        env.put("c", -199.100);
        env.put("s1", "Hello");
        env.put("s2", "Hello");
        env.put("i1", 5);
        env.put("i2", 2);

        // 执行表达式
        Boolean result = (Boolean) compiledExp.execute(env);
        System.out.println(result);  // 输出 true
    }
}

Aviator 表达式引擎确实支持在不仅仅是数字,还包括字符串、正则表达式、布尔值以及实现了 java.lang.Comparable 接口的对象之间进行比较。

Aviator 支持使用比较运算符来比较字符串,例如 !===>>=<<=。下面是一个验证字符串比较的示例:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 字符串比较
 * @author: zhangyanfeng
 * @create: 2023-10-21 16:38
 **/
public class StringComparisonExample {
    public static void main(String[] args) {
        // 编译表达式
        Expression compiledExp = AviatorEvaluator.compile("s1 == s2");

        Map<String, Object> env = new HashMap<String, Object>();
        env.put("s1", "Hello");
        env.put("s2", "World");

        // 执行表达式
        Boolean result = (Boolean) compiledExp.execute(env);
        System.out.println(result);  // 输出 false
    }
}

Aviator 还支持正则表达式匹配操作。下面是一个验证正则表达式匹配的示例:

package org.zyf.javabasic.viator;

import com.google.common.collect.Maps;
import com.googlecode.aviator.AviatorEvaluator;

import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 正则表达式匹配
 * @author: zhangyanfeng
 * @create: 2023-10-21 16:40
 **/
public class RegexMatchingExample {
    public static void main(String[] args) {
        // 添加自定义函数
        AviatorEvaluator.addFunction(new RegexMatchFunction());

        // 定义表达式
        String expression = "regexMatch(s, 'Hello.*')";

        Map<String, Object> env = Maps.newHashMap();
        env.put("s", "Hello, World!");

        try {
            // 解析并计算表达式
            Object result = AviatorEvaluator.execute(expression, env);
            System.out.println(result);  // 输出 true
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


package org.zyf.javabasic.viator;

import com.googlecode.aviator.runtime.type.AviatorBoolean;
import com.googlecode.aviator.runtime.type.AviatorFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @program: zyfboot-javabasic
 * @description: 自定义函数类用于正则表达式匹配
 * @author: zhangyanfeng
 * @create: 2023-10-21 16:41
 **/
public class RegexMatchFunction implements AviatorFunction {
    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        String input = arg1.stringValue(env);
        String pattern = arg2.stringValue(env);

        Pattern compiledPattern = Pattern.compile(pattern);
        Matcher matcher = compiledPattern.matcher(input);

        if (matcher.matches()) {
            return AviatorBoolean.TRUE;
        } else {
            return AviatorBoolean.FALSE;
        }
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17, AviatorObject aviatorObject18) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17, AviatorObject aviatorObject18, AviatorObject aviatorObject19) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject, AviatorObject aviatorObject1, AviatorObject aviatorObject2, AviatorObject aviatorObject3, AviatorObject aviatorObject4, AviatorObject aviatorObject5, AviatorObject aviatorObject6, AviatorObject aviatorObject7, AviatorObject aviatorObject8, AviatorObject aviatorObject9, AviatorObject aviatorObject10, AviatorObject aviatorObject11, AviatorObject aviatorObject12, AviatorObject aviatorObject13, AviatorObject aviatorObject14, AviatorObject aviatorObject15, AviatorObject aviatorObject16, AviatorObject aviatorObject17, AviatorObject aviatorObject18, AviatorObject aviatorObject19, AviatorObject... aviatorObjects) {
        return null;
    }

    @Override
    public String getName() {
        return "regexMatch";
    }

    @Override
    public AviatorObject call(Map<String, Object> map) {
        return null;
    }

    @Override
    public AviatorObject call(Map<String, Object> map, AviatorObject aviatorObject) {
        return null;
    }

    @Override
    public void run() {

    }

    @Override
    public AviatorObject call() throws Exception {
        return null;
    }
}

Aviator 还支持自定义对象之间的比较,前提是这些对象实现了 java.lang.Comparable 接口。

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 自定义对象比较
 * @author: zhangyanfeng
 * @create: 2023-10-21 16:46
 **/
public class CustomObjectComparisonExample {
    public static void main(String[] args) {
        // 自定义对象实现 java.lang.Comparable 接口
        class MyObject implements Comparable<MyObject> {
            private int value;

            public MyObject(int value) {
                this.value = value;
            }

            @Override
            public int compareTo(MyObject other) {
                return Integer.compare(this.value, other.value);
            }
        }

        // 编译表达式
        Expression compiledExp = AviatorEvaluator.compile("obj1 > obj2");

        Map<String, Object> env = new HashMap<String, Object>();
        env.put("obj1", new MyObject(5));
        env.put("obj2", new MyObject(3));

        // 执行表达式
        Boolean result = (Boolean) compiledExp.execute(env);
        System.out.println(result);  // 输出 true
    }
}

6.访问数组和集合

在 Aviator 中,可以访问数组和集合,并进行各种操作,例如访问元素、修改元素、执行迭代等。

访问数组

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 在 Aviator 中,可以使用索引访问数组元素,就像在其他编程语言中一样。
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:02
 **/
public class ArrayAccessExample {
    public static void main(String[] args) {
        // 定义数组
        String[] colors = {"Red", "Green", "Blue"};

        // 创建环境并将数组添加到环境中
        Map<String, Object> env = new HashMap<>();
        env.put("colors", colors);

        // 访问数组元素
        String color = (String) AviatorEvaluator.execute("colors[1]", env);
        System.out.println("Color at index 1: " + color);  // 输出 "Color at index 1: Green"
    }
}

访问集合

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 支持访问集合,您可以通过键来访问集合中的元素,就像在使用 Map 一样
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:04
 **/
public class MapAccessExample {
    public static void main(String[] args) {
        // 定义一个 Map
        Map<String, Integer> scores = new HashMap<>();
        scores.put("Alice", 95);
        scores.put("Bob", 87);
        scores.put("Charlie", 92);

        // 创建环境并将 Map 添加到环境中
        Map<String, Object> env = new HashMap<>();
        env.put("scores", scores);

        // 访问 Map 中的元素
        int aliceScore = (int) AviatorEvaluator.execute("scores['Alice']", env);
        System.out.println("Alice's score: " + aliceScore);  // 输出 "Alice's score: 95"
    }
}

迭代集合

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 支持迭代集合元素,例如使用 for 循环
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:14
 **/
public class CollectionIterationExample {
    public static void main(String[] args) {
        // 定义一个 Map
        Map<String, Integer> scores = new HashMap<>();
        scores.put("Alice", 95);
        scores.put("Bob", 87);
        scores.put("Charlie", 92);

        // 创建环境并将 Map 添加到环境中
        Map<String, Object> env = new HashMap<>();
        env.put("scores", scores);

        // 使用 Java 代码来迭代 Map 并构建结果字符串
        StringBuilder result = new StringBuilder();
        for (Map.Entry<String, Integer> entry : scores.entrySet()) {
            result.append(entry.getKey()).append(": ").append(entry.getValue()).append(" ");
        }

        env.put("result", result.toString());

        // 使用 Aviator 执行表达式
        String script = "result";
        String output = (String) AviatorEvaluator.execute(script, env);

        System.out.println(output);
        // 输出 "Alice: 95 Bob: 87 Charlie: 92 "
    }
}

7.三元操作符

Aviator 支持三元操作符(conditional operator),也被称为条件表达式,用于根据某个条件的结果选择执行不同的操作。三元操作符通常具有以下形式:

condition ? expression_if_true : expression_if_false

其中,condition 是一个布尔表达式,如果为真,将执行 expression_if_true,否则执行 expression_if_false

下面是一个简单的示例,演示如何在 Aviator 中使用三元操作符:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 验证 Aviator 中的三元操作符
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:23
 **/
public class MultipleTernaryOperatorExamples {
    public static void main(String[] args) {
        // 创建一个公共环境
        Map<String, Object> env = new HashMap<>();

        // 示例1
        env.put("a", 1);
        String result1 = (String) AviatorEvaluator.execute("a > 0 ? 'yes' : 'no'", env);
        System.out.println("Example 1: The number " + env.get("a") + " is " + result1);  // 输出 "Example 1: The number 1 is yes"

        // 示例2
        env.put("a", -1);
        String result2 = (String) AviatorEvaluator.execute("a > 0 ? 'yes' : 'no'", env);
        System.out.println("Example 2: The number " + env.get("a") + " is " + result2);  // 输出 "Example 2: The number -1 is no"

        // 示例3
        env.put("a", 0);
        String result3 = (String) AviatorEvaluator.execute("a > 0 ? 'yes' : 'no'", env);
        System.out.println("Example 3: The number " + env.get("a") + " is " + result3);  // 输出 "Example 3: The number 0 is no"
    }
}

8.正则表达式匹配

Aviator 支持类 Ruby 和 Perl 风格的表达式匹配运算,通过=~操作符, 如下面这个例子匹配 email 并提取用户名返回:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 执行正则表达式匹配并提取匹配的内容
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:30
 **/
public class RegexMatchAndExtractExample {
    public static void main(String[] args) {
        String email = "killme2008@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); // killme2008
    }
}

email与正则表达式/([\\w0-8]+@\\w+[\\.\\w+]+)/通过=~操作符来匹配,结果为一个 Boolean 类 型, 因此可以用于三元表达式判断,匹配成功的时候返回$1,指代正则表达式的分组 1,也就是用户名,否则返回unknown。

Aviator 在表达式级别支持正则表达式,通过//括起来的字符序列构成一个正则表达式,正则表 达式可以用于匹配(作为=~的右操作数)、比较大小,匹配仅能与字符串进行匹配。匹配成功后, Aviator 会自动将匹配成功的分组放入$num的变量中,其中$0 指代整个匹配的字符串,而$1表示第一个分组,以此类推。

Aviator 的正则表达式规则跟 Java 完全一样,因为内部其实就是使用java.util.regex.Pattern做编译的。

9.变量的语法糖

Aviator 提供了一种方便的语法糖,允许您访问变量的属性和字段,类似于 Java 中的点操作符。这使得在 Aviator 表达式中更容易地访问对象的属性和字段。

假设您有一个包含员工信息的列表,每个员工对象都有属性 age,您可以使用 Aviator 计算这些员工的平均年龄。

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import lombok.Data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 计算员工年龄平均值
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:37
 **/
public class EmployeeAverageAgeExample {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("John", 30));
        employees.add(new Employee("Alice", 25));
        employees.add(new Employee("Bob", 35));

        // 创建一个环境 Map 并将员工列表放入其中
        Map<String, Object> env = new HashMap<>();
        env.put("employees", employees);

        // 计算平均年龄
        Double totalAge = 0.0;
        for (Employee employee : employees) {
            totalAge += employee.getAge();
        }
        int numEmployees = employees.size();
        Double avgAge = totalAge / numEmployees;

        // 将平均年龄传递给 Aviator 表达式
        env.put("avgAge", avgAge);

        // 使用变量语法糖访问平均年龄
        Double result = (Double) AviatorEvaluator.execute("avgAge", env);

        System.out.println("Average Age: " + result);  // 输出平均年龄
    }

    @Data
    static class Employee {
        private String name;
        private int age;

        public Employee(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
}

假设我们有一个名为 Product 的类,每个产品都有一个名称、价格和生产日期。我们将使用 Aviator 表达式引擎来演示如何使用这个类以及 Aviator 的变量语法糖。

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;
import lombok.Data;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: Aviator 的变量语法糖
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:46
 **/
public class ProductPriceExample {
    public static void main(String[] args) {
        // 创建一个 Product 对象
        Product product = new Product("Laptop", 999.99, new Date());

        // 创建 Aviator 表达式环境
        Map<String, Object> env = new HashMap<>();
        env.put("product", product);

        // 使用变量语法糖访问对象的属性
        double price = (double) AviatorEvaluator.execute("product.price", env);
        String name = (String) AviatorEvaluator.execute("product.name", env);

        System.out.println("Product Name: " + name);  // 输出 "Product Name: Laptop"
        System.out.println("Product Price: $" + price);  // 输出 "Product Price: $999.99"
    }

    @Data
    static class Product {
        private String name;
        private double price;
        private Date productionDate;

        public Product(String name, double price, Date productionDate) {
            this.name = name;
            this.price = price;
            this.productionDate = productionDate;
        }
    }
}

10.nil 对象

nil 在 Aviator 中是一个内置常量,类似于 Java 中的 null,表示空值。但与 Java 中的 null 不同,Aviator 允许在比较运算符(例如==、!=、>、>=、<、<=)中使用 nil,并规定任何对象都比 nil 大,除了 nil 本身。用户传入的变量如果为 null,Aviator 会自动将其替换为 nil。

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * @program: zyfboot-javabasic
 * @description: 验证 Aviator 中的 nil 常量
 * @author: zhangyanfeng
 * @create: 2023-10-23 00:50
 **/
public class AviatorNilValidation {
    public static void main(String[] args) {
        // 比较 nil 是否相等
        boolean isNilEqual = (boolean) AviatorEvaluator.execute("nil == nil");
        System.out.println("Is nil equal to nil? " + isNilEqual);  // 输出 "Is nil equal to nil? true"

        // 使用 nil 进行比较运算
        boolean isGreaterThanNil = (boolean) AviatorEvaluator.execute("3 > nil");
        System.out.println("Is 3 greater than nil? " + isGreaterThanNil);  // 输出 "Is 3 greater than nil? true"

        // 字符串与 nil 连接
        String result = (String) AviatorEvaluator.execute("nil + 'test'");
        System.out.println("Result of nil + 'test': " + result);  // 输出 "Result of nil + 'test': nulltest"

        // 使用变量与 nil 比较
        Integer a = 3;

        // 创建 Aviator 表达式环境
        Map<String, Object> env = new HashMap<>();
        env.put("a", a);

        boolean isAEqualToNil = (boolean) AviatorEvaluator.execute("a == nil", env);
        System.out.println("Is variable 'a' equal to nil? " + isAEqualToNil);  // 输出 "Is variable 'a' equal to nil? false"
    }
}

11.日期比较

当使用 Aviator 表达式引擎验证日期比较时,通常会将日期值放入 Aviator 表达式环境中,并执行比较或计算操作。

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @program: zyfboot-javabasic
 * @description: 演示验证日期比较
 * @author: zhangyanfeng
 * @create: 2023-10-29 17:59
 **/
public class AviatorDateComparison {
    public static void main(String[] args) throws ParseException {
        // 创建日期格式化器
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        // 创建两个日期对象
        Date date1 = sdf.parse("2010-01-01");
        Date date2 = sdf.parse("2010-01-02");

        // 创建 Aviator 表达式环境
        Map<String, Object> env = new HashMap<>();
        env.put("date1", date1);
        env.put("date2", date2);

        // 比较日期是否相等
        boolean isEqual = (boolean) AviatorEvaluator.execute("date1 == date2", env);
        System.out.println("Are the dates equal? " + isEqual);  // 输出 "Are the dates equal? false"

        // 比较日期的大小
        boolean isGreaterThan = (boolean) AviatorEvaluator.execute("date1 > date2", env);
        System.out.println("Is date1 greater than date2? " + isGreaterThan);  // 输出 "Is date1 greater than date2? false"

        // 计算日期的差值(天数差)
        long dateDiff = date2.getTime() - date1.getTime();
        env.put("dateDiff", TimeUnit.DAYS.convert(dateDiff, TimeUnit.MILLISECONDS));

        // 使用变量 dateDiff 计算日期差值
        long calculatedDateDiff = (long) AviatorEvaluator.execute("dateDiff", env);
        System.out.println("Date difference in days: " + calculatedDateDiff);  // 输出 "Date difference in days: 1"
    }
}

12.大数计算和精度

Aviator 表达式引擎自2.3.0版本开始支持大数字计算和特定精度的计算,主要包括 big intdecimal 两种类型。

大数字面量表示

在 Aviator 中,可以使用大数的字面量表示来表示具有高精度的数字。

  • 以大写字母 N 为后缀的整数都被认为是 big int 类型,例如:1N、2N、9999999999999999999999N 等,都是 big int 类型。
  • 超过 long 范围的整数字面量都将自动转换为 big int 类型。
  • 以大写字母 M 为后缀的数字都被认为是 decimal 类型,例如:1M、2.222M、100000.9999M 等,都是 decimal 类型。

用户也可以通过变量传入这两种类型来参与计算。

运算

big intdecimal 的运算与其他数字类型 longdouble 没有太大区别,操作符仍然是一样的。Aviator 重载了基本算术操作符来支持这两种新类型。示例:

package org.zyf.javabasic.viator;

import com.googlecode.aviator.AviatorEvaluator;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;

/**
 * @program: zyfboot-javabasic
 * @description: 验证 Aviator 的大数计算和精度控制功能
 * @author: zhangyanfeng
 * @create: 2023-10-29 18:12
 **/
public class AviatorBigNumberExample {
    public static void main(String[] args) {
        Object rt = AviatorEvaluator.exec("9223372036854775807100.356M * 2");
        System.out.println(rt + " " + rt.getClass());  // 18446744073709551614200.712 class java.math.BigDecimal
        rt = AviatorEvaluator.exec("92233720368547758074+1000");
        System.out.println(rt + " " + rt.getClass());  // 92233720368547759074 class java.math.BigInteger
        BigInteger a = new BigInteger(String.valueOf(Long.MAX_VALUE) + String.valueOf(Long.MAX_VALUE));
        BigDecimal b = new BigDecimal("3.2");
        BigDecimal c = new BigDecimal("9999.99999");
        rt = AviatorEvaluator.exec("a+10000000000000000000", a);
        System.out.println(rt + " " + rt.getClass());  // 92233720368547758089223372036854775807 class java.math.BigInteger
        rt = AviatorEvaluator.exec("b+c*2", b, c);
        System.out.println(rt + " " + rt.getClass());  // 20003.19998 class java.math.BigDecimal
        rt = AviatorEvaluator.exec("a*b/c", a, b, c);
        System.out.println(rt + " " + rt.getClass());  // 2.951479054745007313280155218459508E+34 class java.math.BigDecimal

    }
}
类型转换和提升

big intdecimal 与其他类型的数字进行运算时,根据 long < big int < decimal < double 的规则进行类型提升。也就是说,如果运算的数字类型不一致,结果的类型将是两者之间更“高”的类型。示例:

  • 1 + 3N,结果为 big int4N
  • 1 + 3.1M,结果为 decimal4.1M
  • 1N + 3.1M,结果为 decimal4.1M
  • 1.0 + 3N,结果为 double4.0
  • 1.0 + 3.1M,结果为 double4.1
Decimal 的计算精度

Aviator 默认的计算精度为 MathContext.DECIMAL128,可以根据需要自定义精度。通过以下代码可以设置自定义的精度:

AviatorEvaluator.setMathContext(MathContext.DECIMAL64);

使用 decimal 类型和自定义精度可以确保计算结果满足特定精度要求。有关 decimal 类型的更多精度控制信息,请参考 java.math.BigDecimal 的文档。

13.两种运行模式

Aviator 提供了两种运行模式:执行速度优先和编译速度优先。

  • 执行速度优先(默认模式):在这种模式下,Aviator 会执行时进行一些优化,以提高表达式的执行速度。这是默认的运行模式,不需要额外的设置。

  • 编译速度优先模式:如果更关注编译速度而不是表达式的执行速度,可以将 Aviator 切换到编译速度优先模式。在这个模式下,Aviator 不会进行优化,从而提高了编译速度。

以下是如何切换到编译速度优先模式的示例:

// 切换到编译速度优先模式 
AviatorEvaluator.setOptimize(AviatorEvaluator.COMPILE);

您可以在需要更快的编译速度时使用编译速度优先模式。在大多数情况下,使用默认的执行速度优先模式通常足够快,但编译速度优先模式对于某些特定的使用情境可能会有所帮助。

14.调试信息

Aviator 提供了跟踪(Debug)功能,可以输出生成的字节码,帮助调试和理解表达式的执行过程。以下是如何使用 Aviator 的跟踪功能以及验证的示例:

启用跟踪功能
AviatorEvaluator.setTrace(true);

这将启用跟踪功能,以便可以输出生成的字节码。

设置跟踪输出流(可选)

默认情况下,生成的字节码将输出到标准输出。如果希望将跟踪信息写入文件或其他输出流,可以使用以下方式:

AviatorEvaluator.setTraceOutputStream(new FileOutputStream(new File("aviator.log")));

这将把跟踪信息写入名为 "aviator.log" 的文件中。

参考文章

  1. 官方文档:Home · killme2008/aviatorscript Wiki · GitHub
  2. Aviator规则表达式引擎介绍及源码跟踪_aviatorevaluator_WowVoid的博客-CSDN博客

评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张彦峰ZYF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值