Rhino初試

整理自一篇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的文檔鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市掏愁,隨后出現(xiàn)的幾起案子歇由,更是在濱河造成了極大的恐慌卵牍,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沦泌,死亡現(xiàn)場(chǎng)離奇詭異糊昙,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谢谦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門释牺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人回挽,你說我怎么就攤上這事没咙。” “怎么了千劈?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵祭刚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我墙牌,道長(zhǎng)涡驮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任喜滨,我火速辦了婚禮遮怜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鸿市。我一直安慰自己锯梁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布焰情。 她就那樣靜靜地躺著陌凳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪内舟。 梳的紋絲不亂的頭發(fā)上合敦,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音验游,去河邊找鬼充岛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛耕蝉,可吹牛的內(nèi)容都是我干的崔梗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼垒在,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蒜魄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤谈为,失蹤者是張志新(化名)和其女友劉穎旅挤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伞鲫,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粘茄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秕脓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驹闰。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖撒会,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情师妙,我是刑警寧澤诵肛,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站默穴,受9級(jí)特大地震影響怔檩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蓄诽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一薛训、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧仑氛,春花似錦乙埃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至出吹,卻和暖如春遇伞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捶牢。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工鸠珠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秋麸。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓渐排,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親灸蟆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子飞盆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355