背景
在我们的业务场景中有一个需求,我们有一个配置功能,该功能需要配置两个变量之间比较大小。使用tab比较难表达,所以就提出了,可以让用户写比较简单的函数进行配置。或者选tab进行选择(前段直接将对应的tab字符串拼接来给后端执行)。
或者这么说吧,可以通过字符串的表达的意思,进行执行这个字符串的索要表达的逻辑,且这个逻辑和这个字符串可以自定义。
Aviator
简介
Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值。现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢?
Aviator的设计目标是轻量级和*高性能 ,相比于Groovy、JRuby的笨重,Aviator非常小,加上依赖包也才450K,不算依赖包的话只有70K;当然,Aviator的语法是受限的,它不是一门完整的语言,而只是语言的一小部分集合。
其次,Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都是通过解释的方式运行,而Aviator则是直接将表达式*编译成Java字节码,交给JVM去执行。简单来说,Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎之间。
内部原理
[if !supportLists]1. [endif]任何语言都是通过一步一步的抽象,从硬件原理再到我们人类可以认识的语言。
[if !supportLists]2. [endif]Java语言是基于JVM虚拟机抽象上来的语言,通过编译器可以将我们写的代码进行类加载后编译为JVM可以认识的字节码,JVM在进行编译和运行再变为我们操作系统可以运行的代码,直到二极管三极管可以认识的的高低位。
[if !supportLists]3. [endif]Aviator框架用自己规范最后也编译为JVM虚拟机可以认识的字节码。
基本使用规范
代码演示:
[if !supportLists]1. [endif]需求:前端直接传来一个字符串,通过这个字符串进行相应的逻辑计算。列入A>B 那就是将A>B的计算结果布尔值返回。
package aviator规则引擎;
import com.googlecode.aviator.AviatorEvaluator;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author yuanxindong
* @date 2020/8/9 12:50
*/
public class AviatorDemo3 {
public static void main(String[] args) {
String nameValue = "a";
String name1Value2 = "b";
String expression = nameValue + ">" + name1Value2;
// nameValue
Object execute = compareAandB(nameValue, name1Value2, expression);
System.out.println(execute);
}
private static Object compareAandB(String A, String B, String expression) {
Date dateTime = new Date();
Date dateTime2 = new Date();
Map<String, Object> map = new HashMap<>(4);
map.put(A, dateTime);
map.put(B, dateTime2);
return AviatorEvaluator.execute(expression, map);
}
}
需求2. 设计一个根据付款金额决定是否发送优惠券的规则表达式
package aviator规则引擎;
import com.googlecode.aviator.AviatorEvaluator;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author yuanxindong
* @date 2020/8/9 12:50
*/
public class AviatorDemo3 {
public static void main(String[] args) {
String nameValue = "a";
String name1Value2 = "b";
String expression = nameValue + ">" + name1Value2;
// nameValue
Object execute = compareAandB(nameValue, name1Value2, expression);
System.out.println(execute);
}
private static Object compareAandB(String A, String B, String expression) {
Date dateTime = new Date();
Date dateTime2 = new Date();
Map<String, Object> map = new HashMap<>(4);
map.put(A, dateTime);
map.put(B, dateTime2);
return AviatorEvaluator.execute(expression, map);
}
}
需求3:
1)设计
业务需求:
“1小时,userid,在ip上,触发action 100次报警”
表达式设计:
“redisCount(‘1’,‘hour’,fields(‘userid,ip,action’)) >= 100”
函数说明:
fields() : 获取字段,校验,生成redis key
redisCount():使用 key进行查询,获取redis中存的量且redis +1
package aviator规则引擎;
import com.googlecode.aviator.AviatorEvaluator;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author yuanxindong
* @date 2020/8/9 12:50
*/
public class AviatorDemo3 {
public static void main(String[] args) {
String nameValue = "a";
String name1Value2 = "b";
String expression = nameValue + ">" + name1Value2;
// nameValue
Object execute = compareAandB(nameValue, name1Value2, expression);
System.out.println(execute);
}
private static Object compareAandB(String A, String B, String expression) {
Date dateTime = new Date();
Date dateTime2 = new Date();
Map<String, Object> map = new HashMap<>(4);
map.put(A, dateTime);
map.put(B, dateTime2);
return AviatorEvaluator.execute(expression, map);
}
}