首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 執行 JavaScript 代碼:ScriptEngine 實戰指南

     編輯:Java 相關知識

應用場景

  • 規則引擎:業務規則外部化為 JS 腳本,熱更新無需重啟
  • 動態表單計算:前端邏輯後端復用
  • 模板渲染、數據轉換、腳本化配置

核心步驟

  1. 定義 Java 介面,方法簽名與 JS 函數一致
  2. 使用 ScriptEngineManager 獲取 JS 引擎
  3. engine.eval() 載入腳本文件/字符串
  4. 將引擎轉為 Invocable,通過 getInterface() 獲取 Java 代理對象
  5. 像調用普通 Java 方法一樣調用 JS 函數

完整示例

1. JavaScript 腳本文件

// JavaScriptMethods.js
function execute(s1, s2) {
    return s1 + s2;
}

2. Java 介面定義

public interface Methods {
    String execute(String s1, String s2);
}

3. 執行器

public class JsExecutor {
    public static void main(String[] args) {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js"); // Nashorn (JDK 8-14) / GraalJS (JDK 15+)

        try {
            // 載入外部 JS 文件
            String path = JsExecutor.class.getResource("").getPath();
            engine.eval(new FileReader(path + "JavaScriptMethods.js"));

            // 獲取強類型代理
            if (engine instanceof Invocable) {
                Invocable invocable = (Invocable) engine;
                Methods methods = invocable.getInterface(Methods.class);
                String result = methods.execute("li", "yuncong");
                System.out.println("JS 執行結果: " + result); // liyuncong
            }
        } catch (Exception e) {
            throw new RuntimeException("JS 執行失敗", e);
        }
    }
}

進階用法

傳遞複雜對象

// JS 端
function process(user) {
    return user.name.toUpperCase() + " - " + (user.age + 1);
}

// Java 端
public interface UserProcessor { String process(User user); }

// 執行
UserProcessor processor = invocable.getInterface(UserProcessor.class);
User user = new User("Alice", 25);
System.out.println(processor.process(user)); // ALICE - 26

引擎會自動在 Java Bean 與 JS Object 間雙向轉換。

調用無返回值函數 / 訪問全局變量

engine.eval("var globalConfig = {env: 'prod', version: 1};");
Invocable inv = (Invocable) engine;
inv.invokeFunction("initConfig"); // 調用無參函數
Object config = engine.get("globalConfig"); // 獲取全局變量

引擎選擇與遷移注意

JDK 版本預設引擎備註
JDK 8 - 14NashornJDK 15 標記棄用,JDK 15 移除
JDK 15+無內建需引入 GraalJS: org.graalvm.js:js:23.x

GraalJS 使用方式基本相同,僅需確保類路徑包含依賴。注意:GraalJS 默認啟用多線程隔離,效能更優但啟動稍慢。

安全性考量

  • 不信任的腳本請使用 ScriptContext 限制訪問權限
  • 生產環境建議啟用 --polyglot 沙箱模式
  • 避免在腳本中直接調用 java.lang.Runtime 等危險 API
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved