提示:aviator的demo若干
Aviator 的基本过程是将表达式直接翻译成对应的 java 字节码执行,整个过程最多扫两趟(开启执行优先模式,如果是编译优先模式下就一趟),这样就保证了它的性能超越绝大部分解释性的表达式引擎,测试也证明如此;其次,除了依赖 commons-beanutils 这个库之外(用于做反射)不依赖任何第三方库,因此整体非常轻量级,整个 jar 包大小哪怕发展到现在 5.0 这个大版本,也才 430K。同时, Aviator 内置的函数库非常“节制”,除了必须的字符串处理、数学函数和集合处理之外,类似文件 IO、网络等等你都是没法使用的,这样能保证运行期的安全,如果你需要这些高阶能力,可以通过开放的自定义函数来接入。因此总结它的特点是:
● 高性能
● 轻量级
● 一些比较有特色的特点:
○ 支持运算符重载
○ 原生支持大整数和 BigDecimal 类型及运算,并且通过运算符重载和一般数字类型保持一致的运算方式。
○ 原生支持正则表达式类型及匹配运算符 =~
○ 类 clojure 的 seq 库及 lambda 支持,可以灵活地处理各种集合
● 开放能力:包括自定义函数接入以及各种定制选项
参考
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>5.3.0</version>
</dependency>
import cn.hutool.crypto.digest.DigestUtil;
import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.AviatorEvaluatorInstance;
import com.googlecode.aviator.Expression;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
public class AviatorDemo {
/**
* 数值运算
*/
@Test
public void calculationTest() {
// 模拟入参
String aParam = "1.1";
String bParam = "1.0";
String cParam = "1.0";
// 占位符
String aStr = "arg[1]";
String bStr = "arg[2]";
String cStr = "arg[3]";
// 占位符赋值
String aValue = aStr.replace(aStr, aParam);
String bValue = bStr.replace(bStr, bParam);
String cValue = cStr.replace(cStr, cParam);
// 脚本
String script = "a / ( b + c )";
Map<String, Object> map = new HashMap<>();
// 入参
map.put("a", new BigDecimal(aValue));
map.put("b", new BigDecimal(bValue));
map.put("c", new BigDecimal(cValue));
AviatorEvaluatorInstance instance = AviatorEvaluator.getInstance();
// 语法校验
instance.validate(script);
// 编译脚本 compile(final String cacheKey, final String expression, final boolean cached)
// 参数
// cacheKey: cached 为 true 时,会缓存编译结果,默认缓存的 key 为 script,这里使用 md5 作为 key,这样 key 不会很长
// expression: 脚本
// cached: 设置为 true,否则都生成一个新的匿名类和对象,因此如果频繁调用会占满 JVM 的 metaspace,可能导致 full gc 或者 OOM
Expression exp = instance.compile(DigestUtil.md5Hex(script), script, true);
// 执行脚本
BigDecimal result = (BigDecimal) exp.execute(map);
System.err.println(result);
}
/**
* 布尔表达式运算
*/
@Test
public void boolExpressionTest() {
String script = "a / ( b + c ) == 5 && 3 == 3";
Map<String, Object> map = new HashMap<>();
map.put("a", 100);
map.put("b", 10);
map.put("c", 10);
Expression exp = AviatorEvaluator.getInstance().compile(DigestUtil.md5Hex(script), script, true);
Boolean bool = (Boolean) exp.execute(map);
System.err.println(bool);
}
/**
* 条件语句 if-else(支持复杂嵌套,注意: 若要使用 else if,需写成 elsif)
*/
@Test
public void conditionTest() {
String script = " if(a > b){ " +
" return a - b; " +
" }else{ " +
" return a + b; " +
" } ";
Map<String, Object> map = new HashMap<>();
map.put("a", new BigDecimal("1.1"));
map.put("b", new BigDecimal("1,0"));
Expression exp = AviatorEvaluator.getInstance().compile(DigestUtil.md5Hex(script), script, true);
Object execute = exp.execute(map);
System.out.println(execute);
}
/**
* for 循环
*/
@Test
public void forLoopTest() {
String script = "for i in range(0, 10) { " +
" if (i % 2 == 0) { " +
" continue; " +
" } " +
" println(i); " +
" } ";
Expression exp = AviatorEvaluator.getInstance().compile(DigestUtil.md5Hex(script), script, true);
exp.execute();
}
/**
* while 循环
*/
@Test
public void whileLoopTest() {
String script = "while (a < 5 ) { " +
" a = a + 1; " +
" b = b * 10; " +
" } " +
" return b; ";
Map<String, Object> map = new HashMap<>();
map.put("a", new BigDecimal("1.1"));
map.put("b", new BigDecimal("1.0"));
Expression exp = AviatorEvaluator.getInstance().compile(DigestUtil.md5Hex(script), script, true);
Object execute = exp.execute(map);
System.out.println(execute);
}
}