日期:2014-05-16  浏览次数:20430 次

Mozilla Rhino:使用java语言来解释和执行javascript脚本

Mustang 的脚本引擎

JSR 233 为 Java 设计了一套脚本语言 API。这一套 API 提供了在 Java 程序中调用各种脚本语言引擎的接口。任何实现了这一接口的脚本语言引擎都可以在 Java 程序中被调用。在 Mustang 的发行版本中包括了一个基于 Mozilla Rhino 的 JavaScript 脚本引擎。

Mozilla Rhino

Rhino 是一个纯 Java 的开源的 JavaScript 实现。他的名字来源于 O'Reilly 关于 JavaScript 的书的封面:

Rhino

Rhino 项目可以追朔到 1997 年,当时 Netscape 计划开发一个纯 Java 实现的 Navigator,为此需要一个 Java 实现的 JavaScript —— Javagator。它也就是 Rhino 的前身。起初 Rhino 将 JavaScript 编译成 Java 的二进制代码执行,这样它会有最好的性能。后来由于编译执行的方式存在垃圾收集的问题并且编译和装载过程的开销过大,不能满足一些项目的需求,Rhino 提供了解释执行的方式。随着 Rhino 开放源代码,越来越多的用户在自己的产品中使用了 Rhino,同时也有越来越多的开发者参与了 Rhino 的开发并做出了很大的贡献。如今 Rhino1.6R2 版本将被包含在 Java SE6 中发行,更多的 Java 开发者将从中获益。

Rhino 提供了如下功能

  • 对 JavaScript 1.5 的完全支持
  • 直接在 Java 中使用 JavaScript 的功能
  • 一个 JavaScript shell 用于运行 JavaScript 脚本
  • 一个 JavaScript 的编译器,用于将 JavaScript 编译成 Java 二进制文件

支持的脚本语言

dev.java.net 可以找到官方的脚本引擎的实现项目。这一项目基于BSD License ,表示这些脚本引擎的使用将十分自由。目前该项目已对包括 Groovy, JavaScript, Python, Ruby, PHP 在内的二十多种脚本语言提供了支持。这一支持列表还将不断扩大。

在 Mustang 中对脚本引擎的检索使用了工厂模式。首先需要实例化一个工厂 —— ScriptEngineManager。

// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();

?

ScriptEngineManager 将在 Thread Context ClassLoader 的 Classpath 中根据 jar 文件的 META-INF 来查找可用的脚本引擎。它提供了 3 种方法来检索脚本引擎:

// create engine by name
ScriptEngine engine = factory.getEngineByName ("JavaScript");
// create engine by name
ScriptEngine engine = factory.getEngineByExtension ("js");
// create engine by name
ScriptEngine engine = factory.getEngineByMimeType ("application/javascript");

?

下面的代码将会打印出当前的 JDK 所支持的所有脚本引擎

ScriptEngineManager factory = new ScriptEngineManager();
for (ScriptEngineFactory available : factory.getEngineFactories()) {
    System.out.println(available.getEngineName());
}

?

以下各章节代码将以 JavaScript 为例。

在 Java 中解释脚本

有了脚本引擎实例就可以很方便的执行脚本语言,按照惯例,我们还是从一个简单的 Hello World 开始:

public class RunJavaScript {
    public static void main(String[] args){
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName ("JavaScript");
        engine.eval("print('Hello World')");
    }
}

?

这段 Java 代码将会执行 JavaScript 并打印出 Hello World。如果 JavaScript 有语法错误将会如何?

engine.eval("if(true){println ('hello')");


故意没有加上”}”,执行这段代码 Java 将会抛出一个 javax.script.ScriptException 并准确的打印出错信息:

Exception in thread "main" javax.script.ScriptException: 
sun.org.mozilla.javascript.internal.EvaluatorException: 
missing } in compound statement (<Unknown source>#1) in <Unknown source> 
at line number 1
at ...

?

如果我们要解释一些更复杂的脚本语言,或者想在运行时改变该脚本该如