AviatorScript 表达式引擎

AviatorScript 表达式引擎学习笔记

📚 基础概念

什么是 AviatorScript?

AviatorScript 是一个高性能的 Java 表达式求值引擎,支持大部分运算操作符、少量语句以及自定义函数等功能。

核心特性

  • 高性能:编译执行,支持缓存
  • 功能丰富:支持算术、逻辑、字符串、集合操作
  • 扩展性强:支持自定义函数和变量
  • 语法简洁:类似 Java 的语法风格
  • 类型安全:运行时类型检查

🛠️ 环境配置

Maven 依赖

xml 复制代码
<dependency>
    <groupId>com.googlecode.aviator</groupId>
    <artifactId>aviator</artifactId>
    <version>5.3.3</version>
</dependency>

Gradle 依赖

gradle 复制代码
implementation 'com.googlecode.aviator:aviator:5.3.3'

🚀 基础使用

简单示例

java 复制代码
import com.googlecode.aviator.AviatorEvaluator;
import java.util.HashMap;
import java.util.Map;

public class AviatorBasicDemo {
    public static void main(String[] args) {
        // 1. 简单数学运算
        System.out.println(AviatorEvaluator.execute("1 + 2 * 3")); // 7
        
        // 2. 使用变量
        Map<String, Object> env = new HashMap<>();
        env.put("x", 10);
        env.put("y", 20);
        System.out.println(AviatorEvaluator.execute("x + y", env)); // 30
        
        // 3. 字符串操作
        env.put("name", "张三");
        System.out.println(AviatorEvaluator.execute("'你好,' + name", env)); // 你好,张三
        
        // 4. 逻辑运算
        env.put("age", 25);
        System.out.println(AviatorEvaluator.execute("age >= 18", env)); // true
    }
}

🎯 高级功能

条件表达式

java 复制代码
Map<String, Object> env = new HashMap<>();
env.put("score", 85);

// 三元运算符
String result = (String) AviatorEvaluator.execute(
    "score >= 90 ? '优秀' : score >= 80 ? '良好' : '一般'", env);
System.out.println(result); // 良好

// if-else 语句
String script = """
    if (score >= 90) {
        return '优秀';
    } elsif (score >= 80) {
        return '良好';
    } else {
        return '一般';
    }
    """;
System.out.println(AviatorEvaluator.execute(script, env)); // 良好

集合操作

java 复制代码
Map<String, Object> env = new HashMap<>();
env.put("numbers", Arrays.asList(1, 2, 3, 4, 5));

// 集合过滤
String filterScript = "filter(numbers, lambda(x) -> x > 3)";
System.out.println(AviatorEvaluator.execute(filterScript, env)); // [4, 5]

// 集合映射
String mapScript = "map(numbers, lambda(x) -> x * 2)";
System.out.println(AviatorEvaluator.execute(mapScript, env)); // [2, 4, 6, 8, 10]

// 集合归约
String reduceScript = "reduce(numbers, +, 0)";
System.out.println(AviatorEvaluator.execute(reduceScript, env)); // 15

🔧 自定义函数

创建自定义函数

java 复制代码
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorRuntimeJavaType;

// 自定义函数:计算圆的面积
public class CircleAreaFunction extends AbstractFunction {
    @Override
    public String getName() {
        return "circleArea";
    }
    
    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
        double radius = (Double) arg1.getValue(env);
        double area = Math.PI * radius * radius;
        return AviatorRuntimeJavaType.valueOf(area);
    }
}

使用自定义函数

java 复制代码
public class CustomFunctionDemo {
    public static void main(String[] args) {
        // 注册自定义函数
        AviatorEvaluator.addFunction(new CircleAreaFunction());
        
        Map<String, Object> env = new HashMap<>();
        env.put("r", 5.0);
        
        double area = (Double) AviatorEvaluator.execute("circleArea(r)", env);
        System.out.println("圆的面积: " + area); // 圆的面积: 78.53981633974483
    }
}

⚡ 性能优化

编译和缓存

java 复制代码
import com.googlecode.aviator.Expression;

public class AviatorCompileDemo {
    public static void main(String[] args) {
        // 编译表达式以提高性能
        Expression exp = AviatorEvaluator.compile("x * y + z");
        
        Map<String, Object> env = new HashMap<>();
        env.put("x", 10);
        env.put("y", 20);
        env.put("z", 5);
        
        // 多次执行编译后的表达式
        System.out.println(exp.execute(env)); // 205
        
        // 修改变量值再次执行
        env.put("x", 15);
        System.out.println(exp.execute(env)); // 305
    }
}

性能优化建议

java 复制代码
public class AviatorPerformanceDemo {
    public static void main(String[] args) {
        // 1. 预编译常用表达式
        Expression compiledExp = AviatorEvaluator.compile("x * 0.1 + y * 0.2");
        
        // 2. 启用编译缓存(默认开启)
        AviatorEvaluator.setOption(Options.COMPILE_CACHE, true);
        
        // 3. 批量执行
        Map<String, Object> env = new HashMap<>();
        for (int i = 0; i < 1000; i++) {
            env.put("x", i);
            env.put("y", i * 2);
            compiledExp.execute(env);
        }
    }
}

🏗️ 工作原理

执行流程

  1. 词法分析:将表达式字符串拆分成 token

    arduino 复制代码
    "x + y * 2" → [x, +, y, *, 2]
  2. 语法分析:构建抽象语法树(AST)

    markdown 复制代码
          +
         / \
        x   *
           / \
          y   2
  3. 编译:转换成字节码指令

    markdown 复制代码
    1. 加载变量 x
    2. 加载变量 y
    3. 加载常数 2
    4. 执行乘法 (y * 2)
    5. 执行加法 (x + 结果)
  4. 执行:运行字节码并返回结果

类比理解

  • 词法分析:像读句子时识别单词
  • 语法分析:像理解句子的语法结构
  • 编译:像把中文翻译成英文指令
  • 执行:像按照指令执行操作

📋 实际应用场景

规则引擎

java 复制代码
public class RuleEngineDemo {
    private static final Map<String, Expression> RULES = new HashMap<>();
    
    static {
        // 预编译规则
        RULES.put("vip_discount", AviatorEvaluator.compile(
            "if (totalAmount >= 1000 && isVip) { return 0.8; } else { return 1.0; }"));
        
        RULES.put("shipping_fee", AviatorEvaluator.compile(
            "totalAmount >= 99 ? 0 : 10"));
    }
    
    public static void main(String[] args) {
        Map<String, Object> orderInfo = new HashMap<>();
        orderInfo.put("totalAmount", 1200.0);
        orderInfo.put("isVip", true);
        
        // 计算折扣
        double discount = (Double) RULES.get("vip_discount").execute(orderInfo);
        System.out.println("折扣率: " + discount); // 0.8
        
        // 计算运费
        double shippingFee = (Double) RULES.get("shipping_fee").execute(orderInfo);
        System.out.println("运费: " + shippingFee); // 0
    }
}

动态配置

java 复制代码
// 电商促销规则
Map<String, String> promotionRules = new HashMap<>();
promotionRules.put("双11", "amount > 500 ? amount * 0.7 : amount * 0.9");
promotionRules.put("618", "amount > 300 ? amount * 0.8 : amount");
promotionRules.put("普通日", "amount > 100 ? amount * 0.95 : amount");

// 根据不同节日应用不同规则
String todayRule = promotionRules.get("双11");
double finalPrice = (Double) AviatorEvaluator.execute(todayRule, env);

💡 优势总结

相比硬编码的优势

硬编码方式 AviatorScript 方式
规则写死在代码中 规则可配置化
修改需要重新编译 修改配置即可生效
不易维护 易于维护和扩展
业务逻辑与代码耦合 业务逻辑与代码解耦

适用场景

  • 🎯 规则引擎:业务规则频繁变化
  • 📊 报表计算:动态计算公式
  • 🛒 电商促销:灵活的价格计算
  • 📋 配置管理:可配置的业务逻辑
  • 🔍 数据过滤:动态查询条件

📝 最佳实践

  1. 预编译常用表达式:提高执行性能
  2. 合理使用缓存:避免重复编译
  3. 类型安全:注意变量类型匹配
  4. 异常处理:捕获表达式执行异常
  5. 安全考虑:限制表达式复杂度,防止恶意代码
相关推荐
中东大鹅7 分钟前
SpringBoot实现文件上传
java·spring boot·后端
David爱编程1 小时前
Java中main 方法为何必须是static?
java·后端
追梦人物1 小时前
Uniswap 手续费和协议费机制剖析
前端·后端·区块链
程序员Forlan2 小时前
SpringBoot查询方式全解析
java·spring boot·后端
小奏技术2 小时前
从零到一打造一款提升效率的IDEA插件-根据java doc自动生成枚举代码
后端·intellij idea
PetterHillWater3 小时前
Kimi-K2模型真实项目OOP重构实践
后端·aigc
Moonbit3 小时前
月报 Vol.02:新增条件编译属性 cfg、#alias属性、defer表达式,增加 tuple struct 支持
后端·程序员·编程语言
回家路上绕了弯4 小时前
深度理解 Lock 与 ReentrantLock:Java 并发编程的高级锁机制
java·后端
Captaincc5 小时前
TRAE 首场 Meetup:8月16日,期待与你在北京相聚
前端·后端·trae