Java - Rhino

阅读数:84 评论数:0

跳转到新版页面

分类

python/Java

正文

Rhino 是开源的 JavaScript 引擎,是完全基于 Java 实现。

1、环境

从 Mazilla 网站上下载 Rhino 引擎(本文撰写基于最新的版本 Rhino-1.7R3),下载地址为 http://www.mozilla.org/rhino/。将软件包解压,可以得到 Rhino 源代码、文档、测试代码、样例以及一些小工具,利用这些我们便可以通过多种方式执行 JavaScript 脚本。

2、进入交互模式

进入交互模式有两种方式:使用 js.jar 文件实现和使用 org.mozilla.javascript.tools.shell 实现。

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

或切换到 tools 编译后目录,输入 java org.mozilla.javascript.tools.shell.Main,同样可以进入带提示符 js> 的命令模式。

3、java的嵌入式开发

(1)引入 Rhino JavaScript 工具包 

在您的 Java 项目中使用 Rhino JavaScript 引擎,首先要做的工作是要将其引入到您的项目中,所需要类都在 org.mozilla.javascript命名空间下

 import org.mozilla.javascript.Context; 
 import org.mozilla.javascript.Scriptable;

(2)进入上下文

在导入 Rhino JavaScript 的 Java 包之后,需要创建并进入 Context。本步骤的作用在于构造 JavaScript 的运行环境,Context 中储存了脚本执行的全局环境信息,

 Context cx = Context.enter();

构造 JavaScript 的运行环境非常的简单,只需要调用 Java 类 Context 的静态方法 enter 即可,而无需对 Context 类进行实例化,该方法将会返回 Context 的一个实例。

(3)初始化标准对象

在使用 Rhino 执行脚本之前,必须初始化标准对象(Object,Function 等)

 Scriptable scope = cx.initStandardObjects();

作用域是 JavaScript 中一个相当重要的概念,在本步骤初始化的 scope 变量类似于构造了一个全局对象,而在整个运行过程中 JavaScript 的变量都会作为该对象的一部分,在下文中介绍的在 Java 中调用 JavaScript 变量就是通过该对象实现。初始化标准化对象,需要调用上下文实例的 initStandardObjects 方法,执行结果将会返回一个 Scriptable 实例化对象。

(4)执行 JavaScript 脚本

 Object result = cx.evaluateString(scope, string, error, num, null);

JavaScript 脚本的执行是使用上下文示例中的 evaluateString 方法,执行脚本字符串 string,当脚本中需要使用其它变量时,会在作用域 scope 中寻找所需要的变量,如果发生异常的话则会报告 error 错误信息和所在的行号 num,正确执行结束后会返回一个 Object 对象的运行结果

(5)输出运行的结果

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

 System.out.println(cx.toString(result));

(6)结束上下文

结束上下文是每次使用 Rhino 结束后必须要做的工作,它将移除上下文和当前的线程并做垃圾回收。

 Context.exit();

在每次进入上下文后您都应该调用它退出方法,因为在使用过程中可能会产生异常,所以通常在调用 Context.enter() 进入上下文之后,将退出操作放入对应的 finally 块中。

4、Java和JavaScript对象的相对调用

(1)在 JavaScript 脚本中使用 Java 对象 

将 Java 部分代码或者功能实现作为 JavaScript 一部分,以脚本的方式执行,这种方式在极大程度上可以减少用户为解决个别问题而费尽脑筋。在 JavaScript 中可以直接使用 Java 对象

 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 代码中直接调用 Java 的输出方法,这种方式可能从感觉上不是很舒服,因为需要明确定义 Java 的命名空间等信息。另外,也可以将 Java 对象转换为 JavaScript 对象,并添加到运行环境中,需要添加额外的代码去实现,这种方式有点像 Java 工具包的导入

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

(2)在 Java 中调用 JavaScript 脚本中的变量 

在 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 过程中的某些信息时,请首先考虑该对象。

(3)在 Java 中调用 JavaScript 脚本中的函数 

在前文中我们已经向您展示了如何将 Java 代码以 JavaScript 脚本的方式运行,同样我们也可以将 JavaScript 脚本作为 Java 代码进行实现,这样可以使您的项目复用度极大提高,也将会使您在项目开发过程中更加得心应手,

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

 




相关推荐

1、基本类型 在程序设计中经常用到一系列类型(基本类型),它们需要特殊对待。对于这些类型,Java采取与C和C++相同的方法,也就是说,不用new来创建变量,于是创建一个并非引

1、直接常量 为了编译器可以准确的知道要生成什么样的类型,可以给直接常量后面添加后缀字符标志它的类型,若为L表示long,F表示float,D表示double。也可以利用前缀表示进制,0x表示十六进制

Java完全采用动态内存分配方式。每当想创建新对象时,就需要使用new关键字来构建此对象实例。 1、this 在构造器中,如果为this添加了参数列表,那么就有了

一、类的继承 1、说明 (1)extends关键字用于类的继承。 (2)在C++中,方法的动态绑定是使用virtual关键字来实现的,而在Java中,动态绑定是默认的形为,不需要添加额外的关键字。 (

1、类型信息 指程序能够在运行时发现和使用类型信息,我们一般使用两种方式来实现运行时对象和类的信息:传统的RTTI和反射机制。 (1)class对象 <p

用于描述Java源代码,使得我们能够以将由编译器来测试和验证的格式,存储有关程序的额外信息。使用时在@后面跟注解的名字。 1、预定义的三个注解<

一、创建线程 创建线程有四种方式:继承Thread类、实现Runnable接口、实现Callable接口、通过线程池创建。 1、继承Thread 重写run方法。 class A extends Th

一、Collection接口 Collection接口的iterator和toArray方法都用于获得集合中的“所有元素”。前者返回一个“iterator”对象,后者返回一个包含集合中所有元素的数组。

1.hashCode的存在主要用于查找的快捷性,如hashtable,hastmap等,hashcode是用来在散列存储结构中确定对象的存储地址的。 2.如果两个对象相同,就是适用

Java中的数据类型,可分为两类: 1.基本数据类型,它们之间的比较,应用双等号,比较的是它们的值。 2.复合数据类型(类) 当他们用双等号进行比较的时