Google Aviator:轻量级Java公式引擎完全指南

Google Aviator:轻量级Java公式引擎完全指南

Aviator简介

核心优势

  • 🚀 高性能:通过编译成字节码实现,接近原生Java性能
  • 📦 轻量级:核心jar包仅几百KB,无第三方依赖
  • 🔢 大数运算:内置支持高精度计算(BigDecimal)
  • 🔌 可扩展:支持自定义函数和运算符重载
  • 📝 丰富语法:支持大多数Java运算符和函数调用

典型应用场景

  1. 动态规则计算(如风控规则、定价策略)
  2. 配置文件中的条件表达式
  3. 数据转换和格式化处理
  4. 数学公式计算引擎
  5. 模板引擎中的逻辑运算

核心特性详解

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

自定义函数实现要点

  1. 继承AbstractFunction或现有函数基类
  2. 实现call()方法处理参数
  3. 通过getName()声明函数名称
  4. 注册到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());</
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值