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