Rhino初试

整理自一篇CSDN博客
Rhino 是开源的 JavaScript 引擎,是完全基于 Java 实现,几乎可以使用 JavaScript 完成 Java 所有的工作,而且支持将 JavaScript 编译成 Java 字节码。在 Rhino 环境中既可以使用 JavaScript 的工具,同时也可以非常简单的使用 Java 的工具。

Rhino可以以jar形式导入项目,也可以在控制台运行
jar下载链接

控制台使用Rhino

进入交互模式

打开控制台,并切换 rhino.jar 文件所在的目录,输入java -jar rhino.jar命令,便会出现解释器的版本信息,并进入带提示符 js> 的命令模式。

加载 JavaScript 文件

创建tools.js,其代码如下:

var tools = {};
tools.testPlus = function(num1 , num2){
     return num1 + num2;
}

在命令行中输入 load("C:/tools.js"),完成 tools.js 文件的加载。注意在此处"/"和"\"是有区别的,不能换用。

测试 JavaScript 代码运行

在命令行中输入tools.testPlus(1,2),显示执行结果为 3,证明 JavaScript 代码运行成功。

退出交互模式

退出交互模式可以用Ctrl+Z(Windows 系统)或Ctrl+D(Linux 或 Unix 系统),也可以调用quit()方法退出。

嵌入java或android项目

本部分将向您介绍如何将 Rhino JavaScript 引擎嵌入到你的项目中,从而使你的应用程序增加脚本的支持,提高灵活度。简单而言,Rhino 的作用在于构造一个 JavaScript 运行所需要的运行环境,亦即下面所用的关键词上下文 Context。

在项目中导入的Rhino的jar

下载链接同文章开头

引入构建javascript运行环境所需类
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
...
创建上下文

创建JavaScript运行的Context。本步骤的作用在于构造 JavaScript 的运行环境,Context 中储存了脚本执行的全局环境信息,示例代码如下:
Context cx = Context.enter();

初始化标准对象

在使用 Rhino 执行脚本之前,必须初始化标准对象(Object,Function 等)
Scriptable scope = cx.initStandardObjects();
作用域(scope)是 JavaScript 中一个相当重要的概念,在本步骤初始化的 scope 变量类似于构造了一个全局对象,而在整个运行过程中 JavaScript 的变量都会作为该对象的一部分,在下文中介绍的在 Java 中调用 JavaScript 变量就是通过该对象实现。

执行 JavaScript 脚本

当以上准备工作结束后,便可以执行 JavaScript 语句了,示例代码如下:
Object result = cx.evaluateString(scope,source,sourcename,lineon,null);
JavaScript 脚本的执行可以使用上下文示例的 evaluateString 方法,执行脚本字符串source,当脚本中需要使用其它变量时,会在作用域 scope 中寻找,sourcename(脚本名称)和lineon主要为了方便调试,比如若有报错信息,会附带脚本名称和错误所在行数(根据lineon和脚本字符串计算出),正确执行结束后会返回一个 Object 对象的运行结果。

输出运行的结果

JavaScript 没有独立的输入输出方法,必须借助于宿主环境的输入输出方法,这里使用 Java 的输出机制 System.out.println 方法,示例代码如下:
System.out.println(cx.toString(result));

结束上下文

结束上下文是每次使用 Rhino 结束后必须要做的工作,它将移除上下文和当前的线程并做垃圾回收。示例代码如下:
Context.exit();
在每次进入上下文后您都应该调用它退出。由于在使用过程中可能会产生异常,最好将退出操作放入对应的 finally 块中。

Java 和 JavaScript 交互

从根本上讲在 Java 项目中嵌入 JavaScript 脚本引擎,最重要的一点是实现 Java 和 JavaScript 之间的数据共享。Rhino为我们提供了强大的Java 和 JavaScript 交互的方法。

JavaScript中使用Java的功能

将一部分功能用 Java 实现,并在JavaScript中调用,可以方便解决java转换到JavaScript产生的个别问题,示例代码如下:

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对象共享到JavaScript

可以将 Java 对象转换为 JavaScript 对象,并用putProperty方法添加到运行环境中,示例代码如下:

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 脚本中的变量

可以用于获取脚本运行过程中的一些临时信息变量,示例代码如下:

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 变量,这个是 JavaScript 运行时的全局变量,你可以将它理解成为一个容器,里面包含了 JavaScript 运行过程中的所有信息,所以如果你希望取得 JavaScript 过程中的某些信息,应首先考虑该对象。

在 Java 中调用 JavaScript 脚本中的函数

在前文中介绍了如何在 JavaScript 脚本运行Java函数,同样我们也可以在Java代码中运行JavaScript中的函数,示例代码如下:

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));
}

另附:

在运行环境中导入 JavaScript 工具包

在系统开发过程中,我们经常会使用一些 JavaScript 工具包,如加密工具包等。而使用 Rhino 导入工具包也是非常的简单方便,只需要将工具包文件中的内容以字符的形式在上下文中运行,以后便可以在对应的作用域中直接使用。示例代码如下:

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里的方法,此处无关紧要,略去
    Object result = ct.evaluateString(scope, "test();", null, 1, null);
    System.out.println(result.toString());
} catch (Exception e) {
    e.printStackTrace();
} finally{
    ct.exit();
}

最后,附带Rhino的文档链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,265评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,274评论 1 288
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,087评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,479评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,782评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,218评论 1 207
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,594评论 2 309
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,316评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,955评论 1 237
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,274评论 2 240
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,803评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,177评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,732评论 3 229
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,953评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,687评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,263评论 2 267
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,189评论 2 258