Java知識點總結(動態執行JS程式碼 )
@(Java知識點總結)[Java, 動態位元組碼操作]
JDK6.0之後提供了指令碼引擎功能,讓我們可以執行某些指令碼語言,特別是javascript(javascript是一門解釋性語言,動態性非常好)。
讓JAVA的動態性得到更充分的體現,某些時候可以更加靈活的應對需求的變化。
指令碼引擎介紹:
- 使得 Java 應用程式可以通過一套固定的 介面與各種指令碼引擎 互動,從而達到在 Java 平臺上呼叫各種指令碼語言的目的 。
- Java 指令碼 API 是連通 Java 平臺和指令碼語言 的 橋樑 。
- 可以把一些複雜異變的業務邏輯交給指令碼語言處理,這又大大提高了開發效率。
Java 指令碼 API 為開發者提供瞭如下功能:
-
獲取指令碼程式輸入,通過指令碼引擎執行指令碼並返回執行結果,這是最核心的介面。
- 注意是:介面。 Java可以使用各種不同的實現,從而通用的呼叫 js 、 groovy 、 python 等指令碼。
- 通過 指令碼引擎 的執行上下文在指令碼和 Java 平臺間交換資料。
- 通過 Java 應用程式呼叫指令碼函式。
JS指令碼引擎Rhino
Rhino 是一種使用 Java 語言編寫的 JavaScript 的開源實現,原先由Mozilla開發,現在被整合進入JDK 6.0。
官方首頁
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.URL;
import java.util.List;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Test09 {
// 定義變數,儲存到引擎上下文中
private static void test1(ScriptEngine engine) {
engine.put("msg", "張三是個好學生");
System.out.println(engine.get("msg")); // 獲取變數的值
try {
engine.eval("msg=`java是門好用的語言`;"); // 修改變數的值
} catch (ScriptException e1) {
e1.printStackTrace();
}
System.out.println(engine.get("msg"));
}
// 定義一個物件
private static void test2(ScriptEngine engine) {
String str = "var user = {name:`張三`,age:18,subjects:[`計算機`,`英語`]};";
str += "println(user.name);";
try {
engine.eval(str);
} catch (ScriptException e) {
e.printStackTrace();
}
}
// 定義一個函式
private static void test3(ScriptEngine engine) {
try {
engine.eval("function add(a,b){var sum = a+b;return sum;}");
} catch (ScriptException e) {
e.printStackTrace();
}
try {
// 取得呼叫介面
Invocable jsInvoke = (Invocable) engine;
// 執行指令碼中定義的方法
Object result = jsInvoke.invokeFunction("add", new Object[] { 13, 20 });
System.out.println(result);
} catch (NoSuchMethodException | ScriptException e) {
e.printStackTrace();
}
}
// 匯入其他java包,使用其他包中的java類
private static void test4(ScriptEngine engine) {
String jsCode = "importPackage(java.util); var list = Arrays.asList(["浙江大學","清華大學","北京大學"]); ";
try {
engine.eval(jsCode);
} catch (ScriptException e) {
e.printStackTrace();
}
List<String> list2 = (List<String>) engine.get("list");
for (String temp : list2) {
System.out.println(temp);
}
}
//執行一個js檔案(我們將a.js至於專案的src下即可)
private static void test5(ScriptEngine engine) {
URL is = Test09.class.getClassLoader().getResource("a.js");
Reader r= null;
try {
r = new FileReader(is.getPath());
engine.eval(r);
} catch (FileNotFoundException | ScriptException e) {
e.printStackTrace();
}finally {
try {
r.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// 獲得指令碼引擎
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName("javascript");
test1(engine);
test2(engine); // java 8 出現異常:Caused by: <eval>:1 ReferenceError: "println" is not defined
test3(engine);
test4(engine); // java 8出現異常:Caused by: <eval>:1 ReferenceError: "importPackage" is not defined
test5(engine);
}
}