ScriptEngineManager 獲取 JS 引擎engine.eval() 載入腳本文件/字符串Invocable,通過 getInterface() 獲取 Java 代理對象// JavaScriptMethods.js
function execute(s1, s2) {
return s1 + s2;
}
public interface Methods {
String execute(String s1, String s2);
}
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 - 14 | Nashorn | JDK 15 標記棄用,JDK 15 移除 |
| JDK 15+ | 無內建 | 需引入 GraalJS: org.graalvm.js:js:23.x |
GraalJS 使用方式基本相同,僅需確保類路徑包含依賴。注意:GraalJS 默認啟用多線程隔離,效能更優但啟動稍慢。
ScriptContext 限制訪問權限--polyglot 沙箱模式java.lang.Runtime 等危險 API