Java Scripting API 使用示例

Java Scripting API 包含一組類和接口,在 javax.script 包中定義。這是一個相對比較小的 Java 包,以 ScriptEngineManager 類作為起點。一個 ScriptEngineManager 對象可以通過 JAR 文件服務發現機制來查找腳本引擎,而實例化 ScriptEngine 對象的解析腳本使用專門的腳本語言編寫。更多關于 javax.script 包的詳細信息請看 Java SE 規范//docs.oracle.com/javase/8/docs/api/javax/script/package-summary.html

Nashorn 引擎是 Java SE 開發工具包(JDK)自帶的默認 ECMAScript (JavaScript)引擎。Nashorn 引擎是 Oracle 使用純 Java 開發的,是 OpenJDK 項目的一部分。你可以在下面地址中找到關于 Nashorn 引擎更詳細的信息://openjdk.java.net/projects/nashorn/

雖然 Nashorn 是 Java Scripting API 默認使用的 ECMAScript 引擎,但你也可以使用其他兼容 JSR 223 的腳本引擎,或者你可以實現自己的引擎。該文檔不涉及腳本引擎的實現方法,但最最基礎的級別,你必須實現 javax.script.ScriptEngine 和 javax.script.ScriptEngineFactory 接口。抽象類 javax.script.AbstractScriptEngine 提供了很多默認 ScriptEngine 接口的方法實現。


使用 Java Scripting API 的步驟:

創建一個 ScriptEngineManager 對象.

從管理器對象中獲取 ScriptEngine 對象

使用腳本引擎的 eval() 方法來執行腳本

下面我們提供了幾個例子來展示如何使用 Java Scripting API。為了讓例子盡可能的簡單,我們沒有對執行過程中的異常進行處理。Java Scripting API 的異常有受檢查異常和運行時異常兩種,這些異常必須進行正確處理。在每個例子中,ScriptEngineManager 類的實例是通過 Nashorn 引擎的 getEngineByName() 方法來獲取的。如果指定名稱的引擎不存在,該方法會返回 null 。更多關于 Nashorn 引擎的信息請看 Nashorn User’s Guide.


注意:每個 ScriptEngine 對象都有它獨有的變量作用域。要使用多個變量作用域請看  Example 8.

示例 1 —— 執行腳本語句


在這個例子中,調用腳本引擎實例的 eval() 方法來執行以字符串標識的 JavaScript 代碼。



import javax.script.*;

 

public class EvalScript {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // evaluate JavaScript code

        engine.eval("print('Hello, World')");

    }

}

示例 2 —— 執行腳本文件


在這個例子中, eval() 方法傳遞了一個 FileReader 對象作為參數,從 scripts.js 文件中讀取 JavaScript 代碼。通過封裝不同的輸入流對象作為 reader 來實現從文件、URL 或者其他資源中執行腳本。



import javax.script.*;

 

public class EvalFile {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // evaluate JavaScript code

        engine.eval(new java.io.FileReader("script.js"));

    }

}

示例 3 —— 輸出 Java 對象作為全局變量


在這個例子中,我們創建了一個 File 對象并通過 put() 方法暴露給引擎作為一個名為 file 的全局變量。然后在 JavaScript 代碼中調用 eval() 方法就可以訪問該變量并調用 getAbsolutePath() 方法。


注意:


作為變量的 Java 對象的字段訪問和方法調用語法取決于腳本語言。該例子使用 JavaScript 語法,和 Java 的類似。



import javax.script.*;

import java.io.*;

 

public class ScriptVars {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // create File object

        File f = new File("test.txt");

 

        // expose File object as a global variable to the engine

        engine.put("file", f);

 

        // evaluate JavaScript code and access the variable

        engine.eval("print(file.getAbsolutePath())");

    }

}

示例 4 —— 調用腳本函數


本例中在 JavaScript 代碼中調用 eval() 方法,定義了一個包含單個參數的函數。然后創建 Invocable 對象,并使用其方法 invokeFunction() 來調用這個函數。


注意:


并非所有的腳本引擎都實現了 Invocable 接口。本例中使用 Nashorn 引擎,可以在腳本中調用之前引擎已經定義的函數。


import javax.script.*;

 

public class InvokeScriptFunction {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // evaluate JavaScript code that defines a function with one parameter

        engine.eval("function hello(name) { print('Hello, ' + name) }");

 

        // create an Invocable object by casting the script engine object

        Invocable inv = (Invocable) engine;

 

        // invoke the function named "hello" with "Scripting!" as the argument

        inv.invokeFunction("hello", "Scripting!");

    }

}

示例 5 —— 調用腳本對象的方法


本例中在 JavaScript 代碼中調用 eval() 方法定義包含一個方法的對象。該對象在腳本中通過腳本引擎的 get() 方法暴露給 Java 應用,然后創建一個 Invocable 對象,并通過 invokeMethod() 方法調用對象的方法。


注意:


并非素有的腳本引擎都實現了 Invocable 接口。本例中使用 Nashorn 引擎,可以調用引擎之前已經定義的腳本方法。



import javax.script.*;

 

public class InvokeScriptMethod {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // evaluate JavaScript code that defines an object with one method

        engine.eval("var obj = new Object()");

        engine.eval("obj.hello = function(name) { print('Hello, ' + name) }");

 

        // expose object defined in the script to the Java application

        Object obj = engine.get("obj");

 

        // create an Invocable object by casting the script engine object

        Invocable inv = (Invocable) engine;

 

        // invoke the method named "hello" on the object defined in the script

        // with "Script Method!" as the argument

        inv.invokeMethod(obj, "hello", "Script Method!");

    }

}

示例 6 —— 實現一個包含腳本函數的 Java 接口


本例中在 JavaScript 代碼中調用 eval() 方法來定義一個函數。然后創建一個 Invocable 對象,并通過其getInterface() 方法來創建一個 Runnable 接口對象。接口的方法在腳本函數中實現,這是通過函數名稱匹配的方式實現的(本例中 run() 函數用來實現接口對象的 run() 方法)。最后,啟動一個新的線程來運行腳本函數。



import javax.script.*;

 

public class ImplementRunnable {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // evaluate JavaScript code that defines a function with one parameter

        engine.eval("function run() { print('run() function called') }");

 

        // create an Invocable object by casting the script engine object

        Invocable inv = (Invocable) engine;

 

        // get Runnable interface object

        Runnable r = inv.getInterface(Runnable.class);

 

        // start a new thread that runs the script

        Thread th = new Thread(r);

        th.start();

        th.join();

    }

}

示例 7 —— 在腳本對象方法中實現 Java 接口


本例中在 JavaScript 代碼中調用 eval() 方法來定義一個包含單個方法的對象。該對象在腳本中通過 get() 方法暴露給 Java 應用。然后創建一個 Invocable 對象并通過其 getInterface() 方法來創建一個 Runnable 接口對象。該接口的方法實現是在腳本對象中相同匹配名稱的函數中(本例中對象的 run 方法對應接口的 run 方法的實現)。最后啟動一個新線程來運行腳本對象的方法。



import javax.script.*;

 

public class ImplementRunnableObject {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // evaluate JavaScript code that defines a function with one parameter

        engine.eval("var obj = new Object()")

        engine.eval("obj.run = function() { print('obj.run() method called') }");

 

        // expose object defined in the script to the Java application

        Object obj = engine.get("obj");

 

        // create an Invocable object by casting the script engine object

        Invocable inv = (Invocable) engine;

 

        // get Runnable interface object

        Runnable r = inv.getInterface(obj, Runnable.class);

 

        // start a new thread that runs the script

        Thread th = new Thread(r);

        th.start();

        th.join();

    }

}

示例 8 —— 使用多個變量作用域


本例中腳本引擎的 put() 方法用來設置 x 變量值為 “hello” 字符串對象。緊接著 eval() 方法用來打印默認作用域下的變量值。然后定義一個不同的腳本上下文,并在其作用域下設置相同變量為不同的值(“world” 字符串)。最后在新的腳本上下文中答應該變量,顯示為不同的值。


單一的作用域是 javax.script.Bindings 接口的實例。這個接口繼承自 java.util.Map<String,Object> 接口。一個作用域相當于是成對的名稱和值的列表,其中名稱不能為空。javax.script.ScriptContext 接口通過為每個作用域關聯一個 Bindings 對象來實現對多個作用域的支持。默認情況下,每個腳本應用有自己獨立的上下文。默認的腳本上下文至少有一個作用域,這是通過靜態屬性 ENGINE_SCOPE 來定義的。腳本上下文可以通過 getScopes() 方法來實現對不同作用域的支持。


import javax.script.*;

 

public class MultipleScopes {

    public static void main(String[] args) throws Exception {

        ScriptEngineManager manager = new ScriptEngineManager();

        ScriptEngine engine = manager.getEngineByName("nashorn");

 

        // set global variable

        engine.put("x","hello");

 

        // evaluate JavaScript code that prints the variable (x = "hello")

        engine.eval("print(x)");

 

        // define a different script context

        ScriptContext newContext = new SimpleScriptContext();

        newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);

        Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);

 

        // set the variable to a different value in another scope

        engineScope.put("x", "world");

 

        // evaluate the same code but in a different script context (x = "world")

        engine.eval("print(x)", newContext);

來源:importnew

上一篇: IM 去中心化概念模型與架構設計

下一篇: 如何開始使用 Java 機器學習

分享到: 更多
打印软件免费版 投注单打印软件 七星彩购买前四位网站 开个微信红包群猜大小单双 重庆老是彩开奖号码 pk10七码精准计划群 北京赛车滚雪球计划软件 牌九玩法规则 北京pk10玩法规则介绍 如何买组选6稳赚不赔 牛牛赚钱1元永久提现 北京pk赛车软件下载 赛车值计划软件手机版 欢乐生肖官网 大乐透中奖计算器 麻将技巧秘籍