Aviator是一个开源的Java表达式求值器,不仅支持四则运算、三元运算、逻辑运算,而且其强大的接口支持自定义扩展函数。鉴于此,金融产品重构优化团队在金融产品平台中,选择了这个google的计算引擎,为了扩展我们业务需求,我们自定义了一系列自定义函数,以支撑我们业务场景。
<dependency>
<groupId>com.googlecode.aviatorgroupId>
<artifactId>aviatorartifactId>
<version>3.0.0version>
dependency>
import com.googlecode.aviator.AviatorEvaluator;
public class SimpleExample {
public static void main(String[] args) {
Long result = (Long) AviatorEvaluator.execute("1+2+3");
System.out.println(result);
}
}
第一步:我们可以继承AbstractVariadicFunction,实现相应地接口。这里我们自定义一个多个数字求和的函数。
import com.googlecode.aviator.runtime.function.AbstractVariadicFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDecimal;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.math.BigDecimal;
import java.util.Map;
/**
* @description: 多个数字求和计算(其中任何一个数字为空则作为0处理)
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class SumFunction extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
BigDecimal sum = new BigDecimal(0);
for(AviatorObject each : args){
if(each.getValue(env) == null){
continue;
}
Number value = FunctionUtils.getNumberValue(each, env);
sum = sum.add(new BigDecimal(value.toString()));
}
return new AviatorDecimal(new BigDecimal(sum.toString()));
}
@Override
public String getName() {
return "sum";
}
}
第二步:把函数注册,并调用
AviatorEvaluator.addFunction(new SumFunction());
System.out.println(AviatorEvaluator.execute("sum(1,2)"));
Map<String,Object> evn = new HashMap<String,Object>(){{
put("a",3);
put("b",2);
put("c",5);
put("d",-2);
}};
String expression = " (a > b) && (c > 0 || d > 0) ? a : b";
System.out.println(AviatorEvaluator.execute(expression,evn));
AviatorEvaluator.execute("string.length('hello')"); // 求字符串长度
AviatorEvaluator.execute("string.contains('hello','h')"); //判断字符串是否包含字符串
AviatorEvaluator.execute("string.startsWith('hello','h')"); //是否以子串开头
AviatorEvaluator.execute("string.endsWith('hello','llo')"); 是否以子串结尾
AviatorEvaluator.execute("math.pow(-3,2)"); // 求n次方
AviatorEvaluator.execute("math.sqrt(14.0)"); //开平方根
AviatorEvaluator.execute("math.sin(20)"); //正弦函数
Number类型
:数字类型,支持两种类型,分别对应Java的Long和Double,也就是说任何整数都将被转换为Long,而任何浮点数都将被转换 为Double,包括用户传入的数值也是如此转换。不支持科学计数法,仅支持十进制。如-1、100、2.3等。String类型
:字符串类型,单引号或者双引号括起来的文本串,如’helloworld’,变量如果传入的是String或者Character也将转为String类型。Bool类型
:常量true和false,表示真值和假值,与java的Boolean.TRUE和Boolean.False对应。Pattern类型
: 类似Ruby、perl的正则表达式,以//括起来的字符串,如/\d+/,内部实现为java.util.Pattern。变量类型
:与Java的变量命名规则相同,变量的值由用户传入,如"a"、"b"等nil类型
:常量nil,类似java中的null,但是nil比较特殊,nil不仅可以参与==、!=的比较,也可以参与>、>=、<、<=的比较,Aviator规定任何类型 都n大于nil除了nil本身,nil==nil返回true。用户传入的变量值如果为null,那么也将作为nil处理,nil打印为null。Aviator支持常见的算术运算符,包括+ - * / % 五个二元运算符,和一元运算符"-"。其中 - * / %和一元的"-"仅能作用于Number类型。 "+"不仅能用于Number类型,还可以用于String的相加,或者字符串与其他对象的相加。Aviator规定,任何类型与String相加,结果为String。
Avaitor的支持的逻辑运算符包括,一元否定运算符"!",以及逻辑与的"&&",逻辑或的"||"。逻辑运算符的操作数只能为Boolean。 关系运算符
Aviator支持的关系运算符包括"<" “<=” “>” “>=” 以及"==“和”!=" 。 &&和||都执行短路规则。
关系运算符可以作用于Number之间、String之间、Pattern之间、Boolean之间、变量之间以及其他类型与nil之间的关系比较,不同类型除了nil之 外不能相互比较。
Aviator规定任何对象都比nil大除了nil之外。
Aviator支持所有的Java位运算符,包括"&" “|” “^” “~” “>>” “<<” “>>>”。
匹配运算符"=~"用于String和Pattern的匹配,它的左操作数必须为String,右操作数必须为Pattern。匹配成功后,Pattern的分组将存于变量 $num,num为分组索引。
Aviator没有提供if else语句,但是提供了三元运算符 “?:”,形式为 bool ? exp1: exp2。 其中bool必须为结果为Boolean类型的表达式,而exp1和 exp2可以为任何合法的Aviator表达式,并且不要求exp1和exp2返回的结果类型一致。
nvl:如果为空,设置默认值
/**
* @description: 为空时,设置一个默认值
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class Nvl extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
Number originValue = FunctionUtils.getNumberValue(args[0], env);
Number defaultValue = FunctionUtils.getNumberValue(args[1], env);
return new AviatorDecimal(new BigDecimal(Optional.ofNullable(originValue).orElse(defaultValue).toString()));
}
@Override
public String getName() {
return "nvl";
}
}
sum:多个数字求和
/**
* @description: 多个数字求和计算(其中任何一个数字为空则作为0处理)
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class Sum extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
BigDecimal sum = new BigDecimal(0);
for(AviatorObject each : args){
if(each.getValue(env) == null){
continue;
}
Number value = FunctionUtils.getNumberValue(each, env);
sum = sum.add(new BigDecimal(value.toString()));
}
return new AviatorDecimal(new BigDecimal(sum.toString()));
}
@Override
public String getName() {
return "sum";
}
}
min:多个数字求最小值
/**
* @description: 多个数字求最小值(其中任何一个数字为空则作为0处理)
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class Min extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
List<BigDecimal> list = new ArrayList<>();
for(AviatorObject each : args){
if(each.getValue(env) == null){
continue;
}
Number value = FunctionUtils.getNumberValue(each, env);
list.add(new BigDecimal(value.toString()));
}
list.sort(Comparator.comparing(BigDecimal::doubleValue));
return new AviatorDecimal(new BigDecimal(list.get(0).toString()));
}
@Override
public String getName() {
return "min";
}
}
max:多个数字求最大值
/**
* @description: 多个数字求最大值(其中任何一个数字为空则作为0处理)
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class Max extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
List<BigDecimal> list = new ArrayList<>();
for(AviatorObject each : args){
if(each.getValue(env) == null){
continue;
}
Number value = FunctionUtils.getNumberValue(each, env);
list.add(new BigDecimal(value.toString()));
}
list.sort(Comparator.comparing(BigDecimal::doubleValue).reversed());
return new AviatorDecimal(new BigDecimal(list.get(0).toString()));
}
@Override
public String getName() {
return "max";
}
}
round:四舍五入
/**
* @description: 四舍五入
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class Round extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
Number value = FunctionUtils.getNumberValue(args[0], env);
return new AviatorDecimal(Math.round(value.doubleValue()));
}
@Override
public String getName() {
return "round";
}
}
ceil:向上取整
/**
* @description: 向上取整
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class Ceil extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
Number value = FunctionUtils.getNumberValue(args[0], env);
return new AviatorDecimal(Math.ceil(value.doubleValue()));
}
@Override
public String getName() {
return "ceil";
}
}
floor:向下取整
/**
* @description: 向下取整
* @Date : 2018/9/7 下午5:40
* @Author : 石冬冬-Seig Heil
*/
public class Floor extends AbstractVariadicFunction {
@Override
public AviatorObject variadicCall(Map<String, Object> env, AviatorObject... args) {
Number value = FunctionUtils.getNumberValue(args[0], env);
return new AviatorDecimal(Math.floor(value.doubleValue()));
}
@Override
public String getName() {
return "floor";
}
}
源码地址:https://github.com/killme2008/aviator
相关文档:https://www.yuque.com/boyan-avfmj/aviatorscript
下面的是我的公众号二维码图片,欢迎关注。