目录
一:简介
Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢?
Aviator的设计目标是*轻量级*和*高性能 ,相比于Groovy、JRuby的笨重,Aviator非常小,加上依赖包也才450K,不算依赖包的话只有70K;当然,Aviator的语法是受限的,它不是一门完整的语言,而只是语言的一小部分集合。
其次,Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都是通过解释的方式运行,而Aviator则是直接将表达式*编译成Java字节码,交给JVM去执行。简单来说,Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎之间。
二:特性
Aviator的特性
-
支持大部分运算操作符,包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(=~)、三元表达式?: ,并且支持操作符的优先级和括号强制优先级,具体请看后面的操作符列表。
-
支持大整数和精度运算(2.3.0版本引入)
-
支持函数调用和自定义函数
-
内置支持正则表达式匹配,类似Ruby、Perl的匹配语法,并且支持类Ruby的$digit指向匹配分组。
-
自动类型转换,当执行操作的时候,会自动判断操作数类型并做相应转换,无法转换即抛异常。
-
支持传入变量,支持类似a.b.c的嵌套变量访问。
-
函数式风格的seq库,操作集合和数组
-
性能优秀
三:Aviator的限制
-
没有if else、do while等语句,没有赋值语句,仅支持逻辑表达式、算术表达式、三元表达式和正则匹配。
-
不支持八进制数字字面量,仅支持十进制和十六进制数字字面量。
四:详细见官网
五:案例大全
案例一
public static void main(String[] args) {
// 表达式
String expression = "a-(b-c) > 100";
// 通过compile方法可以将表达式编译成Expression的中间对象
Expression compiledExp = AviatorEvaluator.compile(expression,Boolean.TRUE);
// compiledExp.newEnv(); 相当于创建了一个Map并赋值
Boolean result = (Boolean) compiledExp.execute(compiledExp.newEnv("a", 100.3, "b", 45, "c", -199.100));
System.out.println(result);// false
}
案例二
public static void main(String[] args) {
// 创建解释器
AviatorEvaluatorInstance engine = AviatorEvaluator.newInstance(EvalMode.INTERPRETER);
// 打开跟踪执行(线上不建议开启)
engine.setOption(Options.TRACE_EVAL, true);
Expression exp = engine.compile("score > 80 ? 'good' : 'bad'");
System.out.println(exp.execute(exp.newEnv("score", 100)));// good
System.out.println(exp.execute(exp.newEnv("score", 50)));// bad
}
案例三
public static void main(String[] args) {
Map<String,Object> map = MapUtil.newHashMap();
map.put("aa","美国,中国,德国,法国");
map.put("bb","中国");
// aa的数据是否包含bb
Expression expression = AviatorEvaluator.compile("string.contains(aa,bb)", true);
Boolean result = (Boolean) expression.execute(map);
System.out.println("结果"+result);// 结果true
}
案例四
public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException {
AviatorEvaluator.addStaticFunctions("str", CharSequenceUtil.class);
Map<String,Object> map = MapUtil.newHashMap();
map.put("aa","美国,中国,德国,法国");
Expression expression = AviatorEvaluator.compile("str.isBlank(aa)", true);
Boolean result = (Boolean) expression.execute(map);
System.out.println("结果"+result);// 结果false
}
案例五
public static void main(String[] args) {
// site和receiveCountry可以先进行占位
String expression = "string.contains('A,B,C',site) && string.contains('AA,AC,CC,DD',receiveCountry)";
// 编译表达式
Expression compiledExp = AviatorEvaluator.compile(expression);
Map<String, Object> env = new HashMap<>();
env.put("site", "A");
env.put("receiveCountry", "AA");
// 执行表达式
System.out.println( compiledExp.execute(env));// true
}
案例六
public class MoreStrFunction extends AbstractFunction {
@Override
public AviatorBoolean call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
// 解析到“helllo-word”
String original = FunctionUtils.getStringValue(arg1, env);
// 解析到word
String param = FunctionUtils.getStringValue(arg2, env);
if (CharSequenceUtil.isBlank(param)){
return AviatorBoolean.valueOf(Boolean.FALSE);
}
List<String> originals= CharSequenceUtil.split(original, StrPool.COMMA);
List<String> params= CharSequenceUtil.split(param, StrPool.COMMA);
return AviatorBoolean.valueOf(originals.containsAll(params));
}
@Override
public String getName() {
return "moreStrCompare";
}
}
public static void main(String[] args) {
String expression="moreStrCompare('hello-word',str)";
AviatorEvaluator.addFunction(new MoreStrFunction());
Expression compiledExp = AviatorEvaluator.compile(expression);
//匹配
Map<String, Object> env = new HashMap<>();
env.put("str", "word");
System.out.println(compiledExp.execute(env));// false
}
案例七
public static void main(String[] args) {
String expression="moreStrCompare('hello',site) && string.contains('us,um',receiveCountry) && weight>=0.01 && weight<=4.0 && moreStrCompare('测试',orderTag) && string.contains('1001',id) ";
AviatorEvaluator.addFunction(new MoreStrFunction());
Expression compiledExp = AviatorEvaluator.compile(expression,true);
Map<String, Object> ruleBO=JSONUtil.toBean("{\"id\":3913695,\"site\":\"aaa\",\"receiveCountryIos\":\"aa\",\"receiveProvince\":\"aa\",\"postcode\":\"aa\",\"weight\":0.99,"
+ "\"orderTag\":\"\",\"skuCode\":\"a,b\",\"spuId\":\"1,2,3,4,5\",\"transportType\":\"aaa\",\"orderAmount\":152.75}", Map.class);
//匹配
System.out.println(compiledExp.execute(ruleBO));//false
}