Google Aviator:轻量级Java公式引擎完全指南
Aviator简介
核心优势
- 🚀 高性能:通过编译成字节码实现,接近原生Java性能
- 📦 轻量级:核心jar包仅几百KB,无第三方依赖
- 🔢 大数运算:内置支持高精度计算(BigDecimal)
- 🔌 可扩展:支持自定义函数和运算符重载
- 📝 丰富语法:支持大多数Java运算符和函数调用
典型应用场景
- 动态规则计算(如风控规则、定价策略)
- 配置文件中的条件表达式
- 数据转换和格式化处理
- 数学公式计算引擎
- 模板引擎中的逻辑运算
核心特性详解
1. 类型系统
Aviator支持完整的Java类型系统,包括:
- 基本类型:long/double/boolean等
- 大数类型:BigInteger/BigDecimal
- 集合类型:List/Map/Array
- 自定义对象
// 类型声明示例
"{long} a + b" // 强制返回long类型
"{double} 1/2" // 返回0.5而非0
2. 运算符支持
运算符类型 | 支持示例 |
---|---|
算术运算 | + - * / % |
比较运算 | > >= < <= == != |
逻辑运算 | && || ! |
位运算 | & | ^ ~ << >> |
三元运算 | a > b ? a : b |
3. 内置函数
- 数学函数:
sqrt()/sin()/log()
等 - 字符串函数:
substring()/trim()
- 集合函数:
map()/filter()/reduce()
- 日期函数:
now()/date_add()
自定义函数参考表
函数名称 | 语法示例 | 功能描述 | 实现类 |
---|---|---|---|
特殊字符变量 | $('var.name') |
处理带特殊字符的变量名 | DotVariableFunction |
数组访问 | array(arr, index) |
获取数组指定下标元素 | ArrayFunction |
位操作 | bitSeq(num, pos) |
获取数字指定位的值(0/1) | BitSeqFunction |
类型转换 | {type}expr |
强制转换表达式结果类型 | TypeUtil |
自定义函数实现要点:
- 继承
AbstractFunction
或现有函数基类 - 实现
call()
方法处理参数 - 通过
getName()
声明函数名称 - 注册到
AviatorEvaluatorInstance
本文主要介绍aviator在处理简单运算、特殊字符运算、bit运算、数组运算方面的解决办法。
Spring Boot集成
1. Maven依赖
<dependencies>
<!-- Aviator核心库 -->
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>5.4.1</version> <!-- 使用最新版本 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.28</version>
</dependency>
</dependencies>
2. Expression类结构
/**
* 表达式封装类,实现Serializable以便序列化
*/
public class ExpressionTest implements Serializable {
private static final long serialVersionUID = -1341923453630055435L;
// 自定义函数名称常量
private static final String ARRAY_FUNCTION = "array";
private static final String BIT_SEQ_FUNCTION = "bitSeq";
// Aviator表达式实例(transient不序列化,volatile保证可见性)
private transient volatile Expression expression;
// 表达式中的变量列表
private List<String> variables;
// 原始表达式字符串
private String expr;
// 类型声明(如{long})
private String typeDeclaration;
// 正则表达式模式
private final Pattern pattern = Pattern.compile("\\$\\('([^']*)'");
//判断返回值类型
private final Pattern patternType = Pattern.compile("\\{([^}]*)\\}\\s*(.*)");
public ExpressionTest(String expr) {
extractExpression(expr);
this.expression = buildExpression(expr);
variables = getVariables();
}
}
3. 表达式构建方法
/**
* 构建Aviator表达式
* @param expr 表达式字符串
* @return 编译后的表达式
*/
private Expression buildExpression(String expr) {
// 注册自定义函数
Expression compiledExp = null;
try {
AviatorEvaluatorInstance instance = AviatorEvaluator.getInstance();
registerFunctionIfAbsent(instance, ExternalField.variableMark, new DotVariableFunction());
registerFunctionIfAbsent(instance, ARRAY_FUNCTION, new ArrayFunction());
registerFunctionIfAbsent(instance, BIT_SEQ_FUNCTION, new BitSeqFunction());
compiledExp = AviatorEvaluator.compile(this.expr, true);
} catch (Exception e) {
// 构建计算表达式错误
log.error("Error in constructing the calculation expression: {}", expr, e);
}
return compiledExp;
}
/**
* 函数不存在时注册
*/
private static void registerFunctionIfAbsent(AviatorEvaluatorInstance instance,
String functionName, AviatorFunction function) {
if (MapUtils.isEmpty(instance.getFuncMap()) ||
!instance.getFuncMap().containsKey(functionName)) {
instance.addFunction(function);
}
}
4.类型转换类
public class TypeUtil {
public static BigDecimal toBigDecimal(Object value) {
if (value instanceof Byte) {
return new BigDecimal((Byte) value);
}
if (value instanceof Short) {
return new BigDecimal((Short) value);
}
if (value instanceof Integer) {
return new BigDecimal((Integer) value);
}
if (value instanceof Long) {
return new BigDecimal((Long) value);
}
if (value instanceof Float) {
return BigDecimal.valueOf((Float) value);
}
if (value instanceof Double) {
return BigDecimal.valueOf((Double) value);
}
if (value instanceof String) {
return new BigDecimal((String) value);
}
if (value instanceof BigDecimal) {
return (BigDecimal) value;
}
return null;
}
/**
* 进行数据转化
*
* @param value
* @param targetType
* @param <T>
* @return
*/
public static <T> T convertToType(Object value, Class<T> targetType) {
BigDecimal bigDecimalValue;
try {
bigDecimalValue = Optional.ofNullable(value)
.map(val -> new BigDecimal(value.toString())).get();
} catch (Exception e) {
return (T) value;
}
if (BigDecimal.class.equals(targetType)) {
return targetType.cast(bigDecimalValue);
}
if (Number.class.isAssignableFrom(targetType)) {
try {
if (targetType == Double.class || targetType == double.class) {
return targetType.cast(bigDecimalValue.doubleValue());
} else if (targetType == Float.class || targetType == float.class) {
return targetType.cast(bigDecimalValue.floatValue());
} else if (targetType == Long.class || targetType == long.class) {
return targetType.cast(bigDecimalValue.longValue());
} else if (targetType == Integer.class || targetType == int.class) {
return targetType.cast(bigDecimalValue.intValue());
} else if (targetType == Short.class || targetType == short.class) {
return targetType.cast(bigDecimalValue.shortValue());
} else if (targetType == Byte.class || targetType == byte.class) {
return targetType.cast(bigDecimalValue.byteValue());</