Aviator规则表达式引擎介绍及源码跟踪
Aviator
规则表达式引擎分类
- 编译型规则表达式引擎:预先编译成可执行对象,运行时多次执行;
- 解释型规则表达式引擎:不需要预先进行编译,在运行时,要先进行解释再运行。
Aviator原理及特点
Aviator 的基本过程是将字符串表达式直接翻译成对应的 java 字节码执行,整个过程最多扫两趟(开启执行优先模式,如果是编译优先模式下就一趟),这样就保证了它的性能超越绝大部分解释性的表达式引擎,测试也证明如此;其次,除了依赖 commons-beanutils 这个库之外(用于做反射)不依赖任何第三方库,因此整体非常轻量级,整个 jar 包大小哪怕发展到现在 5.0 这个大版本,也才 430K。同时, Aviator 内置的函数库非常“节制”,除了必须的字符串处理、数学函数和集合处理之外,类似文件 IO、网络等等你都是没法使用的,这样能保证运行期的安全,如果你需要这些高阶能力,可以通过开放的自定义函数来接入。因此总结它的特点是:
- 高性能
- 轻量级
- 开放能力:包括自定义函数接入以及各种定制选项
- 一些比较有特色的特点:
1.支持运算符重载
2.原生支持大整数和 BigDecimal 类型及运算,并且通过运算符重载和一般数字类型保持一致的运算方式。
3.原生支持正则表达式类型及匹配运算符 =~
4.支持lambda ,可以灵活地处理各种集合
Aviator解析
AviatorScript 编译和执行的入口是 AviatorEvaluatorInstance 类,该类的一个实例就是一个编译和执行的单元。
AviatorEvaluator.getInstance() 返回一个全局共享的AviatorEvaluatorInstance 类,没有定制化的需求,该默认引擎已足够我们本次的讲解。
AviatorEvaluatorInstance 入口常用Api:
public final class AviatorEvaluatorInstance {
//编译字符串表达式,cacheKey缓存标识,cached-是否缓存
public Expression compile(final String cacheKey, final String expression, final boolean cached)
//编译aviatorScript脚本文件,cacheKey缓存标识,cached-是否缓存
public Expression compileScript(final String cacheKey, final File file, final boolean cached) throws IOException
//执行字符串表达式,env环境变量,cached-是否缓存Expression对象
public Object execute(final String expression, final Map<String, Object> env,
final boolean cached)
}
示例1、执行字符串表达式
AviatorEvaluatorInstance aviatorEvaluatorInstance = AviatorEvaluator.newInstance();
//1.直接执行表达式
String exp1 = "1+2+3";
Object execute = aviatorEvaluatorInstance.execute(exp1);
System.out.println(execute);//6
String exp2 = "100>1000";
Object execute2 = aviatorEvaluatorInstance.execute(exp2);
System.out.println(execute2);//false
//2.使用环境变量
Map<String, Object> env = AviatorEvaluator.newEnv("a", 100, "b", 200, "c", 300);
String exp3 = "a+b+c";
Object execute3 = aviatorEvaluatorInstance.execute(exp3,env);
System.out.println(execute3);//600
String exp4 = "a+b==c";
Object execute4 = aviatorEvaluatorInstance.execute(exp4,env);
System.out.println(execute4);//false
//访问环境变量数组和集合
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
int[] nums = new int[5];
for(int i=0;i<nums.length;i++){
nums[i]=i;
}
Map<String,Object> map2 = new HashMap<String,Object>();
map2.put("date","2021-08-21");
Map<String,Object> map3 = new HashMap<String,Object>();
map3.put("list",list);
map3.put("nums",nums);
map3.put("map2",map2);
//hello world
System.out.println(AviatorEvaluator.execute("list[0]+' '+list[1]",map3));
//nums[0]+nums[1]+nums[2]=3
System.out.println(AviatorEvaluator.execute("'nums[0]+nums[1]+nums[2]='+ (nums[0]+nums[1]+nums[2])",map3));
//当前时间为:2021-08-21
System.out.println(AviatorEvaluator.execute("'当前时间为:'+map2.date",map3));
}
示例2、执行/导入函数
AviatorEvaluatorInstance aviatorEvaluatorInstance = AviatorEvaluator.newInstance();
//1.使用自有函数
System.out.println(AviatorEvaluator.execute("string.substring('habcello',1,3)"));//ab
System.out.println(AviatorEvaluator.execute("string.contains(\"abc\",\"ab\")"));//true
//2.导入静态方法
aviatorEvaluatorInstance.addStaticFunctions("StringUtils",StringUtils.class);
System.out.println(aviatorEvaluatorInstance.execute("StringUtils.isBlank('abc')"));//false
//3.导入实例方法
aviatorEvaluatorInstance.