2012年10月2日 星期二

[轉載] Java SE 6.0 內建 Javascript 引擎測試

轉載來源

前言 :
Java SE 6.0 採納 JSR 223 建議,使得 Java 能夠與眾多 Script 語言協同運作
透過 Java 定義的標準 API,能夠讓 Script 直接存取和控制 Java 的物件
而Java 應用程式當中也能夠直接內嵌 Script 環境

範例說明 :
底下將會帶幾個範例, 來說明這個 Java 的 JavaScript 引擎能夠達成的工作 :
- 範例01 : 第一個 Hello World 程式, 直接將 JavaScript 代碼丟入 JS Engine 的 eval 函式執行.
package john.js;

import javax.script.*;

public class JSHello {
    public static void main(String args[]) {
        ScriptEngineManager mgr = new ScriptEngineManager(); // 建立一個 Script 管理員
        ScriptEngine jsEngine = mgr.getEngineByName("JavaScript"); // 取得 Javascript 引擎
        try {
          jsEngine.eval("print('Hello, world!')"); // 透過 Javascript 引擎解譯 print('hello, world') 命令
        } catch (ScriptException ex) {
            ex.printStackTrace();
        }    
    }
}

- 範例02:執行外部 javasript 檔案, 這裡是直接把含 JavaScript 代碼(Hello.js) 的內容透過 InputStream 丟給 JS Engine 的 eval API 執行.
package john.js;

import javax.script.*;
import java.io.*;

public class JSRunExtendFile {
    public JSRunExtendFile() {
        ScriptEngineManager engineMgr = new ScriptEngineManager();
        ScriptEngine engine = engineMgr.getEngineByName("ECMAScript");      
        try {
            InputStream is = new FileInputStream(new File("Hello.js"));
            Reader reader = new InputStreamReader(is);
            engine.eval(reader);
        } catch (ScriptException ex) {
            ex.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        JSRunExtendFile ref = new JSRunExtendFile();  
    }
}

- 範例03:透過 Invocable 介面喚起 Javascript 函數.
package john.js;

import javax.script.*;

public class JSInvokeFunction {

    public static void main(String[] args) {
        ScriptEngineManager engineMgr = new ScriptEngineManager();
        ScriptEngine jsEngine = engineMgr.getEngineByName("ECMAScript");
        try {
            jsEngine.eval("function sayHello() {"
                    + "  println('Hello, world!');" + "}");
            Invocable invocableEngine = (Invocable) jsEngine;
            invocableEngine.invokeFunction("sayHello");
        } catch (ScriptException ex) {
            ex.printStackTrace();
        } catch (NoSuchMethodException nsme) {
            nsme.printStackTrace();
        }
    }
}

- 範例04:Script 直接存取 Java 物件
package john.js;

import javax.script.*;
import java.util.*;

public class JSAccessJavaObject {

    public static void main(String[] args) {
        List namesList = new ArrayList();
        namesList.add("Jill");
        namesList.add("Bob");
        namesList.add("Laureen");
        namesList.add("Ed");
        ScriptEngineManager engineMgr = new ScriptEngineManager();
        ScriptEngine jsEngine = engineMgr.getEngineByName("ECMAScript");
        jsEngine.put("namesListKey", namesList); // 將 java 變數指定給 javascript 環境中的
                                                    // nameListKey 變數
        System.out.println("Executing in script environment...");
        try {
            // 列印 Java 的 nameList 變數內容,並新增一個 Dana 字串資料到 List 尾端
            jsEngine.eval("var x;" + "var names = namesListKey.toArray();"
                    + "for(x in names) {" + "  println(names[x]);" + "}"
                    + "namesListKey.add(\"Dana\");");
        } catch (ScriptException ex) {
            ex.printStackTrace();
        }
        System.out.println("Executing in Java environment...");
        for (String name : namesList) {
            System.out.println(name);
        }
    }
}

- 範例05:透過 Invocable 將參數值傳遞給 Javascript 中的函數
package john.js;

import javax.script.*;
import java.util.*;

public class JSPassValueToFunction {

    public static void main(String[] args) {
        List namesList = new ArrayList();
        namesList.add("Jill");
        namesList.add("Bob");
        namesList.add("Laureen");
        namesList.add("Ed");
        ScriptEngineManager engineMgr = new ScriptEngineManager();
        ScriptEngine jsEngine = engineMgr.getEngineByName("ECMAScript");
        Invocable invocableEngine = (Invocable) jsEngine;
        try {
            jsEngine.eval("function printNames1(namesList) {" + "  var x;"
                    + "  var names = namesList.toArray();"
                    + "  for(x in names) {" + "    println(names[x]);" + "  }"
                    + "}" + "function addName(namesList, name) {println('addName: Add '+name);"
                    + "  namesList.add(name);" + "}");
            invocableEngine.invokeFunction("printNames1", namesList);
            invocableEngine.invokeFunction("addName", namesList, "Dana");
        } catch (ScriptException ex) {
            ex.printStackTrace();
        } catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        }
    }
}

補充說明 :
* 純種 Java 與 Javascript 結合
將Script整合進應用程式所能達到的彈性空間的確十分強大
如果能在我們開發的系統也提供Scripting的能力,除了強化擴充性之外,整個系統的質感也是提升不少…爽度up!up!
但以往要達成這目標,有個難處,就是解釋並執行Script用的Interpreting Engine那裡來,自己寫顯然是太累了…。
Java 6這回帶來了好消息:Scripting API,在Java系統中結合Scripting再也不難了,你只需要import javax.script.*; ...

沒有留言:

張貼留言