使用表达式计算库Aviator可能会踩的坑,你必须知道

498 阅读1分钟

简单介绍

Aviator是一个高性能、轻量级的基于java实现的表达式引擎,它动态地将String类型的表达式编译成Java ByteCode并交给JVM执行。

想了解这个库的中文使用文档的,可以点击Aviator

可以添加pom依赖

<dependency>
    <groupId>com.googlecode.aviator</groupId>
    <artifactId>aviator</artifactId>
    <version>5.2.5</version>
</dependency>

一般来说,可以使用AviatorEvaluator.execute方法来进行表达式计算

public static Object execute(String expression, Map<String, Object> env)

expression是表达式,比如"x*1.5+30"

env是参数与参数值的映射关系,比如<"x",3>

调用方法后的计算结果就是3*1.5+30,即34.5,是一个浮点数。

容易踩到的坑

AviatorEvaluator.execute的返回结果是Object,但这个Object不是某个固定的子类,它的返回值可能是BigInt、double、Decimal、甚至是Boolean,具体类型取决于你的表达式定义,参考此文章

如果你希望获取到的最终结果是一个统一的浮点数,则需要写一个转换方法,举个例子

public double convertToDouble(Object obj) {
    if (obj instanceof Boolean) {
        return (Boolean) obj ? 1 : 0;
    } else if (obj instanceof Long) {
        return ((Long) obj).doubleValue();
    } else if (obj instanceof Double) {
        return (Double) obj;
    } else {
        return 0;
    }
}

性能优化

适用于表达式不会频繁变动的场景。

可以将AviatorEvaluator.execute拆成两步,先compile,然后再execute,compile的第二个参数为true,表示使用缓存,当该参数为true时,会先从缓存里面寻找是否已有该表达式,如果有,则直接返回,没有则创建一个新的表达式,并且写入缓存中。

        // 将字符串表达式解析为 Expression 对象
        Expression compileExp = AviatorEvaluator.compile(str, true);
        // 执行Expression 对象的 execute(),获取字符串表达式运算后结果
        return compileExp.execute(map);