Google Aviator:轻量级Java公式引擎完全指南
Google Aviator:轻量级Java公式引擎完全指南
文章目录
- Google Aviator:轻量级Java公式引擎完全指南
-
- Aviator简介
- Spring Boot集成
-
- 1. Maven依赖
- 2. Expression类结构
- 3. 表达式构建方法
- 4.类型转换类
- 5.自定义函数
-
- 1.特殊字符函数
- 2.位运算函数
- 3.数组运算函数
- 6. 表达式求值方法
- 7.完整示例
- 使用示例
-
- 1. 基本算术运算
- 2. 数组操作
- 3. 位操作
- 高级特性
-
- 1. 类型声明
- 2. 特殊变量名处理
- 最佳实践
-
- 1. 性能优化
- 2. 安全建议
- 3. 异常处理
- 常见问题
-
- 1. 变量未定义
- 2. 类型不匹配
- 3. 性能问题
- 4. 复杂表达式调试
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)
BitSeqFunction
{type}expr
TypeUtil
自定义函数实现要点:
- 继承
AbstractFunction
或现有函数基类 - 实现
call()
方法处理参数 - 通过
getName()
声明函数名称 - 注册到
AviatorEvaluatorInstance
本文主要介绍aviator在处理简单运算、特殊字符运算、bit运算、数组运算方面的解决办法。
Spring Boot集成
1. Maven依赖
<dependencies> <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 * @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());</