| 动态调用动态语言之Java脚本API |
|
|
|
|
| 来源: 作者: 添加日期:2007-11-16 19:33:58 点击次数: |
|
许多脚本引擎在 eval() 调用之间维持全局变量和函数的状态。但是有一点值得格外注意,Java 脚本 API 并不要求脚本引擎提供这一特性。本文中所使用的 JavaScript、Groovy 和 JRuby 脚本引擎确实在 eval() 调用之间维持了这些状态。
清单 4 中的代码在前一个示例的基础上做了几分修改。原来的 invokeScriptFunctionFromJava() 方法在调用 sayHello() JavaScript 函数时没有使用 ScriptEngine 的 eval() 方法或 JavaScript 代码。与此不同,清单 4 中的方法使用 Java 脚本 API 的 javax.script.Invocable 接口调用由脚本引擎所维持的函数。invokeScriptFunctionFromJava() 方法将脚本引擎对象传递给 Invocable 接口,然后对该接口调用 invokeFunction() 方法,最终使用给定的参数调用 sayHello() JavaScript 函数。如果调用的函数需要返回值,则 invokeFunction() 方法会将值封装为 Java 对象类型并返回。
清单 4. invokeScriptFunctionFromJava 方法
private static void invokeScriptFunctionFromJava(ScriptEngine engine) throws ScriptException, NoSuchMethodException { Invocable invocableEngine = (Invocable) engine; invocableEngine.invokeFunction("sayHello", "from Java"); } | 使用代理实现高级脚本调用
当脚本函数或方法实现了一个 Java 接口时,就可以使用高级 Invocable。Invocable 接口定义了一个 getInterface() 方法,该方法使用接口做为参数并且将返回一个实现该接口的 Java 代码对象。从脚本引擎获得代理对象之后,可以将它作为正常的 Java 对象对待。对该代理调用的方法将委托给脚本引擎通过脚本语言执行。
注意,清单 4 中没有 JavaScript 代码。Invocable 接口允许 Java 代码调用脚本函数,而无需知道其实现语言。如果脚本引擎无法找到给定名称或参数类型的函数,那么 invokeFunction() 方法将抛出一个 java.lang.NoSuchMethodException。
Java 脚本 API 并不要求脚本引擎实现 Invocable 接口。实际上,清单 4 中的代码应该使用 instanceof 运算符确保脚本引擎在转换(cast)之前实现了 Invocable 接口。
清单 3 和 清单 4 中的示例展示了 Java 代码如何调用脚本语言中定义的函数或方法。您可能会问:脚本语言中编写的代码是否可以反过来对 Java 对象调用方法呢?答案是可以。清单 5 中的 invokeJavaFromScriptFunction() 方法显示了如何使脚本引擎能够访问 Java 对象,以及脚本代码如何才能对这些 Java 对象调用方法。明确的说,invokeJavaFromScriptFunction() 方法使用脚本引擎的 put() 方法将 HelloScriptingWorld 类的实例本身提供给引擎。当引擎拥有 Java 对象的访问权之后(使用 put() 调用所提供的名称),eval() 方法脚本中的脚本代码将使用该对象。
清单 5. invokeJavaFromScriptFunction 和 getHelloReply 方法
private static void invokeJavaFromScriptFunction(ScriptEngine engine) throws ScriptException { engine.put("helloScriptingWorld", new HelloScriptingWorld()); engine.eval( "println('Invoking getHelloReply method from JavaScript...');" + "var msg = helloScriptingWorld.getHelloReply(vJavaScript');" + "println('Java returned: ' + msg)" ); }
/** Method invoked from the above script to return a string. */ public String getHelloReply(String name) { return "Java method getHelloReply says, 'Hello, " + name + "'"; } | 清单 5 中的 eval() 方法调用中所包含的 JavaScript 代码使用脚本引擎的 put() 方法调用所提供的变量名称 helloScriptingWorld 访问并使用 HelloScriptingWorld Java 对象。清单 5 中的第二行 JavaScript 代码将调用 getHelloReply() 公有 Java 方法。getHelloReply() 方法将返回 Java method getHelloReply says, 'Hello, <parameter>' 字符串。eval() 方法中的 JavaScript 代码将 Java 返回值赋给 msg 变量,然后再将其本新闻共 6页,当前在第 4页 1 2 3 4 5 6 |
|
| |