整理自一篇CSDN博客
Rhino 是開源的 JavaScript 引擎啊终,是完全基于 Java 實(shí)現(xiàn)镜豹,幾乎可以使用 JavaScript 完成 Java 所有的工作,而且支持將 JavaScript 編譯成 Java 字節(jié)碼蓝牲。在 Rhino 環(huán)境中既可以使用 JavaScript 的工具趟脂,同時(shí)也可以非常簡(jiǎn)單的使用 Java 的工具。
Rhino可以以jar形式導(dǎo)入項(xiàng)目例衍,也可以在控制臺(tái)運(yùn)行
jar下載鏈接
控制臺(tái)使用Rhino
進(jìn)入交互模式
打開控制臺(tái)昔期,并切換 rhino.jar 文件所在的目錄已卸,輸入java -jar rhino.jar命令,便會(huì)出現(xiàn)解釋器的版本信息硼一,并進(jìn)入帶提示符 js> 的命令模式累澡。
加載 JavaScript 文件
創(chuàng)建tools.js,其代碼如下:
var tools = {};
tools.testPlus = function(num1 , num2){
return num1 + num2;
}
在命令行中輸入 load("C:/tools.js")般贼,完成 tools.js 文件的加載愧哟。注意在此處"/"和"\"是有區(qū)別的,不能換用哼蛆。
測(cè)試 JavaScript 代碼運(yùn)行
在命令行中輸入tools.testPlus(1,2)蕊梧,顯示執(zhí)行結(jié)果為 3,證明 JavaScript 代碼運(yùn)行成功人芽。
退出交互模式
退出交互模式可以用Ctrl+Z(Windows 系統(tǒng))或Ctrl+D(Linux 或 Unix 系統(tǒng))望几,也可以調(diào)用quit()方法退出。
嵌入java或android項(xiàng)目
本部分將向您介紹如何將 Rhino JavaScript 引擎嵌入到你的項(xiàng)目中萤厅,從而使你的應(yīng)用程序增加腳本的支持橄抹,提高靈活度。簡(jiǎn)單而言惕味,Rhino 的作用在于構(gòu)造一個(gè) JavaScript 運(yùn)行所需要的運(yùn)行環(huán)境楼誓,亦即下面所用的關(guān)鍵詞上下文 Context。
在項(xiàng)目中導(dǎo)入的Rhino的jar
下載鏈接同文章開頭
引入構(gòu)建javascript運(yùn)行環(huán)境所需類
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
...
創(chuàng)建上下文
創(chuàng)建JavaScript運(yùn)行的Context名挥。本步驟的作用在于構(gòu)造 JavaScript 的運(yùn)行環(huán)境疟羹,Context 中儲(chǔ)存了腳本執(zhí)行的全局環(huán)境信息,示例代碼如下:
Context cx = Context.enter();
初始化標(biāo)準(zhǔn)對(duì)象
在使用 Rhino 執(zhí)行腳本之前禀倔,必須初始化標(biāo)準(zhǔn)對(duì)象(Object榄融,F(xiàn)unction 等)
Scriptable scope = cx.initStandardObjects();
作用域(scope)是 JavaScript 中一個(gè)相當(dāng)重要的概念陶贼,在本步驟初始化的 scope 變量類似于構(gòu)造了一個(gè)全局對(duì)象窝爪,而在整個(gè)運(yùn)行過程中 JavaScript 的變量都會(huì)作為該對(duì)象的一部分振劳,在下文中介紹的在 Java 中調(diào)用 JavaScript 變量就是通過該對(duì)象實(shí)現(xiàn)料滥。
執(zhí)行 JavaScript 腳本
當(dāng)以上準(zhǔn)備工作結(jié)束后,便可以執(zhí)行 JavaScript 語句了髓霞,示例代碼如下:
Object result = cx.evaluateString(scope,source,sourcename,lineon,null);
JavaScript 腳本的執(zhí)行可以使用上下文示例的 evaluateString 方法半火,執(zhí)行腳本字符串source塞赂,當(dāng)腳本中需要使用其它變量時(shí)邑闺,會(huì)在作用域 scope 中尋找跌前,sourcename(腳本名稱)和lineon主要為了方便調(diào)試,比如若有報(bào)錯(cuò)信息陡舅,會(huì)附帶腳本名稱和錯(cuò)誤所在行數(shù)(根據(jù)lineon和腳本字符串計(jì)算出)抵乓,正確執(zhí)行結(jié)束后會(huì)返回一個(gè) Object 對(duì)象的運(yùn)行結(jié)果。
輸出運(yùn)行的結(jié)果
JavaScript 沒有獨(dú)立的輸入輸出方法灾炭,必須借助于宿主環(huán)境的輸入輸出方法章鲤,這里使用 Java 的輸出機(jī)制 System.out.println 方法,示例代碼如下:
System.out.println(cx.toString(result));
結(jié)束上下文
結(jié)束上下文是每次使用 Rhino 結(jié)束后必須要做的工作咆贬,它將移除上下文和當(dāng)前的線程并做垃圾回收。示例代碼如下:
Context.exit();
在每次進(jìn)入上下文后您都應(yīng)該調(diào)用它退出帚呼。由于在使用過程中可能會(huì)產(chǎn)生異常掏缎,最好將退出操作放入對(duì)應(yīng)的 finally 塊中。
Java 和 JavaScript 交互
從根本上講在 Java 項(xiàng)目中嵌入 JavaScript 腳本引擎煤杀,最重要的一點(diǎn)是實(shí)現(xiàn) Java 和 JavaScript 之間的數(shù)據(jù)共享眷蜈。Rhino為我們提供了強(qiáng)大的Java 和 JavaScript 交互的方法。
JavaScript中使用Java的功能
將一部分功能用 Java 實(shí)現(xiàn)沈自,并在JavaScript中調(diào)用酌儒,可以方便解決java轉(zhuǎn)換到JavaScript產(chǎn)生的個(gè)別問題,示例代碼如下:
Context ct = Context.enter();
Scriptable scope = ct.initStandardObjects();
String str = "var test={};";
str += "test.call=function(){return 'Successful!';};";
str += "java.lang.System.out.println(test.call())";
ct.evaluateString(scope, str, null, 1, null);
可以在JavaScript使用Rhino提供的importPackage和importClass枯途,詳見文末鏈接
將Java對(duì)象共享到JavaScript
可以將 Java 對(duì)象轉(zhuǎn)換為 JavaScript 對(duì)象忌怎,并用putProperty方法添加到運(yùn)行環(huán)境中,示例代碼如下:
Context ct = Context.enter();
Scriptable scope = ct.initStandardObjects();
Object out = Context.javaToJS(System.out, scope);
ScriptableObject.putProperty(scope, "out", out);
ct.evaluateString(scope, "out.println('Successful!')", null, 1, null);
在 Java 中獲取 JavaScript 腳本中的變量
可以用于獲取腳本運(yùn)行過程中的一些臨時(shí)信息變量酪夷,示例代碼如下:
Context ct = Context.enter();
Scriptable scope = ct.initStandardObjects();
ct.evaluateString(scope, "var test = 'Successful';", null, 1, null);
Object jsObject = scope.get("test" , scope);
if (jsObject == Scriptable.NOT_FOUND) {
System.out.println("test is not defined.");
} else {
System.out.println("test is " + Context.toString(jsObject));
}
在上述的示例代碼中榴啸,我們同樣用到了 scope 變量,這個(gè)是 JavaScript 運(yùn)行時(shí)的全局變量晚岭,你可以將它理解成為一個(gè)容器鸥印,里面包含了 JavaScript 運(yùn)行過程中的所有信息,所以如果你希望取得 JavaScript 過程中的某些信息坦报,應(yīng)首先考慮該對(duì)象库说。
在 Java 中調(diào)用 JavaScript 腳本中的函數(shù)
在前文中介紹了如何在 JavaScript 腳本運(yùn)行Java函數(shù),同樣我們也可以在Java代碼中運(yùn)行JavaScript中的函數(shù)片择,示例代碼如下:
Context ct = Context.enter();
Scriptable scope = ct.initStandardObjects();
ct.evaluateString(scope,"function test(name){return 'Successful!'+name;}", null, 1, null);
Object functionObject = scope.get("test" , scope);
if (!(functionObject instanceof Function)) {
System.out.println("test is undefined or not a function.");
} else {
Object testArgs[] = {"Ceven"};
Function test = (Function)functionObject;
Object result = test.call(ct, scope, scope, testArgs);
System.out.println(Context.toString(result));
}
另附:
在運(yùn)行環(huán)境中導(dǎo)入 JavaScript 工具包
在系統(tǒng)開發(fā)過程中潜的,我們經(jīng)常會(huì)使用一些 JavaScript 工具包,如加密工具包等构回。而使用 Rhino 導(dǎo)入工具包也是非常的簡(jiǎn)單方便夏块,只需要將工具包文件中的內(nèi)容以字符的形式在上下文中運(yùn)行,以后便可以在對(duì)應(yīng)的作用域中直接使用纤掸。示例代碼如下:
Context ct = Context.enter();
Scriptable scope = ct.initStandardObjects();
String filename=System.getProperty("user.dir")+"/demo/test.js";
try {
LineNumberReader reader = new LineNumberReader(new
FileReader(filename));
String temp = null;
StringBuffer sb = new StringBuffer();
while((temp = reader.readLine()) != null){
sb.append(temp).append("\n");
}
ct.evaluateString(scope, sb.toString(), null, 1, null)脐供;
//test()是test.js里的方法,此處無關(guān)緊要借跪,略去
Object result = ct.evaluateString(scope, "test();", null, 1, null);
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace();
} finally{
ct.exit();
}
最后政己,附帶Rhino的文檔鏈接