众所周知,各种语言都有各自的特点,有的语言可以通过动态类型或动态闭包之类的特性为我们带来好处。许多资料都介绍了如何通过特定语言中的具体特性来简化编程,或者使用应用程序具有炫酷的功能,如此等等。但是,用户可能只会使用脚本实现 Java 应用程序中的一部分,因此这里有一个经常被人忽略的问题:应该在何时以何种方式使用脚本语言?
在本文中,我将介绍 Scripting API 中的一些高级概念,并演示它们如何帮助您在 Java 应用程序中成功地使用脚本。
在 JVM 中使用脚本语言的基本条件是拥有一个可通过 Java 访问的解释程序(也称作引擎)。有两种常用的方法可实现此目的:在 Java 中实现引擎或在本机语言解释程序外设计一个 Java 封装器。脚本引擎的特性各不相同(详见下文),但是其中很少能代表每个解释程序的核心功能。每个引擎都应该能够为脚本的执行(evaluation)提供上下文,并且显然应该能够执行脚本。
在最简单的场景中,我们将在 Java 应用程序中针对一些语言实例化一个脚本引擎,并绑定一些变量为引擎提供上下文,然后在某个时刻执行脚本。此后,我们还可以从引擎上下文获取一些变量值,因为被执行的代码可以修改(或设置)这些值。
显然,框架需要抽象出各种脚本引擎并借此为 Java 应用程序创建通用的脚本支持。Java SE 6 中的 Scripting API( javax.script)就是出于这种目的。它支持简单的引擎注册、通过工厂方法实例化引擎,以及在方法之间共享上下文。
在本文中,我将主要介绍其他一些方面。如今,许多可用的脚本引擎都向开发人员提供了较多的特性用于简化脚本执行。其中一个特性便是能够调用脚本中定义的独立的函数和对象方法。在一些语言中,您甚至还可以在脚本中实现整个 Java 接口并在 Java 中把它们当作常规对象使用。我们将看到,这些特性可以极大地影响我们在应用程序中使用脚本的方式。但是首先,我必须了解 Scripting API 如何支持这些特性。
javax.script.Invocable
Scripting API 的主要设计目的之一就是尽可能的实现通用性。这样众多脚本引擎便可以依照它。鉴于此,javax.script.ScriptEngine 接口只定义了最基本的脚本引擎操作:变量绑定和脚本执行。脚本引擎可以实现的所有其他高级特性都封装在一个单独的接口中,这样开发人员便可以轻易地判断特定引擎的特征并适当地使用它。这种体系结构还允许通过此 API 使用非常简单的引擎。
函数
在以下示例中,我将演示 Invocable 接口。首先,我将创建一个简单的脚本(本文的所有示例都将通过 JavaScript 实现,因此可以使用 JKD 6 中的 Rhino 引擎 来执行它们):
function sayHello(name) {
println("Hello " + name);
}
这个简单的 JavaScript 示例位于 function.js 文件中(并且可从本文的 参考资料 部分获得),其中定义了一个 sayHello 函数,用于向标准输出打印文本。现在,我们来看看如何使用 Scripting API 调用这种函数。
package net.scriptinginjava.invocable;
import java.io.FileReader;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class InvocableTest {
public static void main(String[] args) throws Exception {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("js");
if (engine instanceof Invocable) {
engine
.eval(new FileReader(
"src/net/scriptinginjava/invocable/function.js"));
((Invocable) engine).invokeFunction("sayHello", "World");
}
}
}
这个 Java 应用程序将实例化 ScriptEngineManager 类,并使用该实例获取需要的脚本引擎,然后使用该引擎处理脚本。
Invocable 接口的使用非常有趣。如您所见,如果引擎实现了 Invocable 接口,则 Java 开发人员可以使用它的 InvokeFunction 方法调用之前被处理脚本中的函数。该方法使用函数名称作为第一个参数,另一个参数是 Object 变量(varargs)的变量名称。在本例中,代码将调用 sayHello 函数和将 World 变量传递给该函数。结果,代码将通过标准输出打印出“Hello World”文本。
2015年全国职称计算机考试教材(2007模 .. 定价:¥225 优惠价:¥213 更多书籍 | |
全国职称计算机考试速成过关系列套装:W .. 定价:¥133 优惠价:¥133.0 更多书籍 |