純種Java與JavaScript的結合
JavaScript是個廣泛應用的描述性語言,除了製作動態網頁外,常常可以看到各種工具使用各種Script來讓使用者有更彈性的設定,例如:
- 報表工具(如JasperReport)可以使用用Script自定欄位的顯示格式。
- 各種Workflow、BPM的工具也可以使用Script訂定各站過站時的邏輯。
- 在ERP中可以使用Script來設定成本計算公式。
- 在MES中可以使用Script來設定良率計算公式。
- …
將Script整合進應用程式所能達到的彈性空間的確十分強大,如果能在我們開發的系統也提供Scripting的能力,除了強化擴充性之外,整個系統的質感也是提升不少…爽度up!up!
但以往要達成這目標,有個難處,就是解釋並執行Script用的Interpreting Engine那裡來,自己寫顯然是太累了…。
Java 6這回帶來了好消息:Scripting API,在Java系統中結合Scripting再也不難了,你只需要import javax.script.*;
不可免俗的,還是讓我們來Hello一下吧:
import javax.script.*;
class HelloScript {
public static void main(String args[])
{
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
try {
jsEngine.eval("print('Hello, world!')");
} catch (ScriptException ex) {
ex.printStackTrace();
}
}
}
是的…我在Java程式中使用JavaScript印出了Hello, world!
只需要幾行而已,取得ScriptEngine,然後將要執行的Script傳入eval()中就好了。
不過,通常要讓Script在系統中派上用場,你需要更完全的整合:在Script中要能使用Java物件、在Script中要能使用Java API、Script的執行結果也要可以回報給Java、在Java中也要可以呼叫Script的method。
接著,讓我們來一一擊破…
1. 在Script中使用Java物件:
// 先在Java中產生一個ArrayList
List
namesList.add("Jill");
namesList.add("Bob");
namesList.add("Laureen");
namesList.add("Ed");
// 取得Script Engine
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
// 把ArrayList物件透過Engine傳進去,取名叫namesListFromJava
jsEngine.put("namesListFromJava", namesList);
System.out.println("==== Executing in script environment... ====");
try {
// 執行Script,注意,此時已經可以在Script中使用namesListFromJava這個
// 由Java傳入的物件了
jsEngine.eval("var x;" +
"var names = namesListFromJava.toArray();" +
"for(x in names) {" +
" println(names[x]);" +
"}" +
"namesListFromJava.add(\"Dana\");");
} catch (ScriptException ex) {
ex.printStackTrace();
}
程式執行結果如下
==== Executing in script environment... ====
Jill
Bob
Laureen
Ed
2. 使用Java呼叫JavaScript Method,並取得其回傳值:
// getting engine
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
// 必須將Engine轉型成Invocable
Invocable invocableEngine = (Invocable)jsEngine;
try {
jsEngine.eval("function sumTwoValue(var1,var2) {" +
" return var1 + var2;" +
"}");
// 在Java中呼叫Script Method並印出回傳值
System.out.println("return value from javascript is : " +
invocableEngine.invokeFunction("sumTwoValue", 3, 4));
} catch (ScriptException ex) {
ex.printStackTrace();
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
執行結果如下
return value from javascript is : 7.0
3. 在Script中使用Java API:
// getting engine
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
try {
jsEngine.eval(
"importPackage(javax.swing);" +
"var optionPane = " +
" JOptionPane.showMessageDialog(null, 'Hello, world!');");
} catch (ScriptException ex) {
ex.printStackTrace();
}
程式執行結果如下:
可以發現,我輕鬆的在JavaScript中叫出了一個Swing對話盒,向各位說「Hello, world!」。
JDK6 野馬與Script的整合,的確讓牠更狂野奔放了:D
3 則留言:
請問可以在script中建立JDBC的連結嗎?
想要查詢資料庫
可以,但是比較麻煩,建議你寫一個class,把資料庫存取的功能包裝起來,然後在Script中使用這個class。
請問有可能用 javascript 去 parse 網頁的資料並且回傳 DOM 相關的資訊回來給 java 嗎? (會這樣想, 是因為 javascipt parse HTML 出來的 DOM tree 與 java 用外加的 parser 取得的 DOM tree 並不依樣).
張貼留言