google aviator:Java逻辑公式引擎

背景

在我们的业务场景中有一个需求,我们有一个配置功能,该功能需要配置两个变量之间比较大小。使用tab比较难表达,所以就提出了,可以让用户写比较简单的函数进行配置。或者选tab进行选择(前段直接将对应的tab字符串拼接来给后端执行)。

或者这么说吧,可以通过字符串的表达的意思,进行执行这个字符串的索要表达的逻辑,且这个逻辑和这个字符串可以自定义。

Aviator

简介

Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢?

Aviator的设计目标是轻量级和*高性能 ,相比于Groovy、JRuby的笨重,Aviator非常小,加上依赖包也才450K,不算依赖包的话只有70K;当然,Aviator的语法是受限的,它不是一门完整的语言,而只是语言的一小部分集合。

其次,Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都是通过解释的方式运行,而Aviator则是直接将表达式*编译成Java字节码,交给JVM去执行。简单来说,Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎之间。

内部原理

  1. 任何语言都是通过一步一步的抽象,从硬件原理再到我们人类可以认识的语言。
  2. Java语言是基于JVM虚拟机抽象上来的语言,通过编译器可以将我们写的代码进行类加载后编译为JVM可以认识的字节码,JVM在进行编译和运行再变为我们操作系统可以运行的代码,直到二极管三极管可以认识的的高低位。
  3. Aviator框架用自己规范最后也编译为JVM虚拟机可以认识的字节码。

 

基本使用规范

 

官方详细文档: https://code.google.com/archive/p/aviator/wikis/User_Guide_zh.wiki

  1. 官方文档会讲的很清楚很多细节,在这里不做赘述

 

代码示例, 判断某个字符是否存在

 Object object = AviatorEvaluator.execute("string.contains(\"test\", 
 string.substring('hello', 1, 2))");  // true
 System.out.println(object);

判断两个时间大小

        String nameValue = "a";
        String name1Value2 = "b";
        String expression = nameValue + ">" + name1Value2;
        // nameValue
        Object execute = compareAandB(nameValue, name1Value2, expression);
        System.out.println(execute);

传入变量  替换

        String name = "小龙";
        Map<String,Object> env = new HashMap<>();
        env.put("name", name);
        String result = (String) AviatorEvaluator.execute(" 'Hello ' + name ", env);
        System.out.println(result);
 Aviator的内置函数用法 获取字符长度

        String str = "带你学习使用Aviator";
        Map<String,Object> env1 = new HashMap<>();
        env1.put("str",str);
        Long length = (Long)AviatorEvaluator.execute("string.length(str)",env1);
        System.out.println(length);
compile用法
        String expression1 = "a-(b-c)>100";
        Expression compiledExp = AviatorEvaluator.compile(expression1);
        Map<String, Object> env2 = new HashMap<>();
        env2.put("a", 100.3);
        env2.put("b", 45);
        env2.put("c", -129.100);
        Boolean result1 = (Boolean) compiledExp.execute(env2);
        System.out.println(result1);
通过上面的代码片段可以看到
使用compile方法,先生成了 Expression 最后再由
Expression.execute,然后传入参数 map,进行计算
这么做的目的是,在我们实际使用过程中
很多情况下,我们要计算的公式都是一样的,只是每次的参数有所区别。
我们可以把一个编译好的Expression 缓存起来。
这样每次可以直接获取我们之前编译的结果直接进行计算,避免Perm区OutOfMemory

Aviator本身自带一个全局缓存
如果决定缓存本次的编译结果,只需要
Expression compiledExp = AviatorEvaluator.compile(expression,true);

这样设置后,下一次编译同样的表达式,Aviator会自从从全局缓存中,拿出已经编译好的结果,不需要动态编译。如果需要使缓存失效,可以使用

AviatorEvaluator.invalidateCache(String expression);

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值