Java 的脚本引擎(Script Engine)是 Java 语言的一部分,允许开发者在 Java 应用程序中嵌入和执行脚本语言。它提供了一种灵活的方式来动态执行代码,进行计算和逻辑处理。以下是对 Java 脚本引擎的详细介绍:

背景与用途

Java 脚本引擎是 Java 6 引入的,属于 javax.script 包的一部分。它使得 Java 应用程序能够执行多种脚本语言(如 JavaScript、Groovy、Ruby 等),这对于需要动态行为或灵活配置的应用程序非常有用。

核心接口

Java 脚本引擎主要通过以下几个核心接口进行操作:

  • ScriptEngineManager
    • 用于创建脚本引擎的工厂类。可以通过它获取支持特定脚本语言的引擎实例。
  • ScriptEngine
    • 代表一个脚本引擎的实例。提供了执行脚本和管理脚本上下文的方法。
    • 主要方法:
      • eval(String script):执行给定的脚本并返回结果。
      • put(String key, Object value):将变量添加到引擎的上下文中。
      • get(String key):从上下文中获取变量的值。
  • Bindings
    • 用于存储脚本引擎的变量和参数。可以在脚本中访问和修改这些变量。

支持的脚本语言

Java 脚本引擎支持多种脚本语言,最常用的包括:

  • JavaScript:通过 Nashorn 引擎(在 Java 8 中引入,Java 15 后被移除)。
  • Groovy:一种动态语言,常用于构建脚本和 DSL(领域特定语言)。
  • Ruby:通过 JRuby 支持。
  • Python:通过 Jython 支持。

优势

  • 动态性:可以在运行时动态执行代码,适合需要灵活配置的应用。
  • 多语言支持:支持多种脚本语言,开发者可以选择最适合其需求的语言。
  • 集成性:可以与 Java 代码无缝集成,利用 Java 的强大功能和库。

注意事项

  • 脚本引擎的性能可能不如纯 Java 代码,尤其是在频繁调用时。
  • 安全性:执行不受信任的脚本可能导致安全问题,因此需要谨慎处理。
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author : zanglikun
 * @date : 2025/1/14 下午1:49
 * @desc : 表达式工具
 */
public class ScriptEngineUtil {

    private static ScriptEngine engine;

    static {
        engine = new ScriptEngineManager().getEngineByName("JavaScript");
        addCustomMethods(engine);
    }


    private static void addCustomMethods(ScriptEngine engine) {
        // 添加自定义方法到引擎
        engine.put("includes", (IncludesFunction) (String str, String substring) -> str.contains(substring));
        engine.put("includesAny", (IncludesFunction) (String realVar, String configVar) ->
                CollectionUtil.contains(StrUtil.split(configVar,","), realVar));
    }

    // 自定义方法接口
    @FunctionalInterface
    public interface IncludesFunction {
        boolean includes(String str, String substring);
    }

    private static boolean evaluateExpression(ScriptEngine engine, String expression, Map<String, Object> params) throws ScriptException {
        // 将参数注入到表达式中
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            // 将参数替换为其值
            expression = expression.replace(key, value instanceof String ? "\"" + value + "\"" : value.toString());
        }
        // 执行表达式并返回结果
        return (Boolean) engine.eval(expression);
    }

    @SneakyThrows
    public static boolean evaluateExpression(String expression, Map<String, Object> params) throws ScriptException {
        if (StringUtils.isBlank(expression)){
            return true;
        }
        // 将参数注入到表达式中
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            // 将参数替换为其值
            expression = expression.replace(key, value instanceof String ? "\"" + value + "\"" : value.toString());
        }
        // 执行表达式并返回结果
        return (Boolean) engine.eval(expression);
    }


    public static void main(String[] args) {
        // 创建一个脚本引擎
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");

        // 添加自定义方法
        addCustomMethods(engine);

        // 示例参数
        Map<String, Object> params = new HashMap<>();
        params.put("key1", 1); // 可以是 1 或 0
        params.put("key2", 1); // 可以是 1 或 0
        params.put("key3", "YWJG,OTHER_TYPE"); // 示例字符串

        // 示例表达式
        String expression1 = "(key1 != 1 && key2 == 1)";
        String expression4 = "(key1 != 1 && includes(key3, 'YWJG'))";
        String expression5 = "(includes(key3,'YWJG'))";

        // 验证表达式
        try {
            System.out.println("Expression 1: " + evaluateExpression(engine, expression1, params)); // false
            System.out.println("Expression 4: " + evaluateExpression(engine, expression4, params)); // false
            System.out.println("Expression 5: " + evaluateExpression(engine, expression5, params)); // true
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}

注意事项

JDK15移除库,不支持功能了,如果有高 JDK 的场景,各位自行询问 GPT 引入外部库,或新类型的脚本。

特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取最新全部资料 ❤

免责声明:
本站文章旨在总结学习互联网技术过程中的经验与见解。任何人不得将其用于违法或违规活动!所有违规内容均由个人自行承担,与作者无关。