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));
        }
    
        // 自定义方法接口
        @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博客搜索:标题关键字。以获取最新全部资料 ❤