资源描述
JavaJava 脚本言程序手册语员脚本言程序手册语员(Java Scripting Programmers Guide)(Java Scripting Programmers Guide)原作:Sun Microsystems,Inc翻:春利译郝 我的博客:http:/ 目录1.Java 脚本 API 的内容.22 脚本包.23 例子.23.1 Hello Word!.23.2 评估脚本文件.33.3 脚本变量.43.4 调用脚本函数和方法.43.5 在脚本中插入 Java 接口.63.6 多重域的脚本.74 JavaScript 脚本引擎.75 从 JavaScript 到 Java 的通讯.85.2 声明和使用 Java 数组.95.3 实现 Java 接口.95.4 解决重载.106 实现自己的脚本引擎.107 参考资料.108 译注.101.Java脚本API的内容 脚本言有以下有用的特点。语拥易性简易性简:大多数脚本言都可以的被予型。通常情况下,不需要特声明就可以在代中语动态赋别码生成一个新的量,可变以根据需要用它存储不同的目。而且,标脚本言可以自大多数量的型,语动转换变例如可以根据自己的需要自由的将你数字 10 和文字串10行。进变换品原型迅速产开发品原型迅速产开发:可以避免你编辑-编译-行程序言的,直接做到执这种语编译步骤编辑-行。执程序的展和定制扩程序的展和定制扩:可以把程序分成多个区,比如,定脚本、商算你块设业运/和算等。规则财务运程序的程序的 shellshell命令行命令行:程序的、行调试执/配置等情况,目前有很多程序都有至少基于 WEB 的 GUI 工具。但是,系管理统员/程序配置人通常都先使用命令行工具。因此,准的文本言代替了那些有同功能的等的程序。员优标语拥样对Java 脚本 API 是了在为Java 代下使用脚本引擎,而且不需要依存于脚本言的框架。利用码语Java 脚本 API,将可以订制/可以的程序用扩张Java写,而将挑定制脚本言的工作交端用。使得书选语给终户这Java 程序在程序不需要员开发时考什的展言。虑选择么样扩语只要使用依照 JSR-223 API准的程序情况下,标开发那么用户就可以任何一个选择基于JSR-223准的脚本言。标语2 脚本包 Java 脚本功能包含于 javax.script 包中。是一个相小巧的这对简单API。脚本 API 的始点位于开ScriptEngineManager。类一个 ScriptEngineManager 目是用标jar 文件服的机制找到脚本引擎。也可以将用来务发现你解析被特定的法写的语书脚本言的语ScriptEngine 目例化。以下是使用脚本标实API 最的。简单步骤1.生成一个 ScriptEngineManager 目标 2.从管理中(ScriptEngineManager 目标)取得 ScriptEngine 目标 3.使用 ScriptEngine 目的标eval 方法价脚本评 从在始我将要看一些脚本。从些范例中可以理解现开们这对你JavaScript 起到一定的助帮,可能是不必要的。3 例子 3.1 Hello Word!通过 ScriptEngineManager例使用实getEngineByName 方法,向 JavaScript 引擎例提出求。在脚本引擎中,实请了为被指定的文字串作为 JavaScript 代行,需要用码运调eval 方法。当然,正使用常理是必的。确异处须 不用也知道,说这里不再做明。说import javax.script.*;public class EvalScript public static void main(String args)throws Exception /JavaScript code in a String ScriptEngineManager factory=new ScriptEngineManager();/create a JavaScript engine ScriptEngine engine=factory.getEngineByName(JavaScript);/evaluate JavaScript code from String engine.eval(print(Hello,World);3.2 评估脚本文件 个例子中,我将用一个以这们调java.io.Reader 形接受脚本代的势码eval 方法。根据被指定取器的内容,脚本将被读行。使用个方法,可以行通入流可能包含的取器如文件、执这执过输读URL 和 classpath源中可以取的脚本。资读import javax.script.*;public class EvalFile public static void main(String args)throws Exception /create a script engine manager ScriptEngineManager factory=new ScriptEngineManager();/create JavaScript engine ScriptEngine engine=factory.getEngineByName(JavaScript);/evaluate JavaScript code from given file-specified by first argument engine.eval(new java.io.FileReader(args0);假文本文件“设test.js”中包含有以下代码那前面的么Java 文件可以如下行执println(This is hello from test.js);java EvalFile test.js3.3 脚本量变 在 java 程序中包含脚本引擎或者是脚本的情况下,程序目将作全局量在脚本中公。在个例子中,标为变开这里这将演示程序目作全局量在脚本中公的方法。在程序中制作一个标为变开java.io.File,并同公一个全局量,将其命样开变名“为file”。脚本可以量。例如访问变在脚本中可以用调public 方法。于对Java 目、方法以及字段的方标访问法,因脚本言的不同,方法也不一。语访问样JavaScript 基本上支持大多数“自然的”Java法。语public class ScriptVars public static void main(String args)throws Exception ScriptEngineManager manager=new ScriptEngineManager();ScriptEngine engine=manager.getEngineByName(JavaScript);File f=new File(test.txt);/expose File object as variable to script engine.put(file,f);/evaluate a script string.The script accesses file /variable and calls method on it engine.eval(print(file.getAbsolutePath();3.4 用脚本函数和方法调 有些候,特定的脚本函数会被反用。例如,程序菜功能可以通脚本时复调单过来。实现凭借菜的作理器可以单时间动处用特定的脚本函数。下面的例子中,演示了从调Java 代中用特定的脚本函数。码调import javax.script.*;public class InvokeScriptFunction public static void main(String args)throws Exception ScriptEngineManager manager=new ScriptEngineManager();ScriptEngine engine=manager.getEngineByName(JavaScript);/JavaScript code in a String String script=function hello(name)print(Hello,+name);/evaluate script engine.eval(script);/javax.script.Invocable is an optional interface./Check whether your script engine implements or not!/Note that the JavaScript engine implements Invocable interface.Invocable inv=(Invocable)engine;/invoke the global function named hello inv.invokeFunction(hello,Scripting!);如果脚本言语(例如 JavaScript)是基于目是目指向的情况,可以通脚本目用脚本方法。标说标过标调import javax.script.*;public class InvokeScriptMethod public static void main(String args)throws Exception ScriptEngineManager manager=new ScriptEngineManager();ScriptEngine engine=manager.getEngineByName(JavaScript);/JavaScript code in a String.This code defines a script object obj /with one method called hello.String script=var obj=new Object();obj.hello=function(name)print(Hello,+name);/evaluate script engine.eval(script);/javax.script.Invocable is an optional interface./Check whether your script engine implements or not!/Note that the JavaScript engine implements Invocable interface.Invocable inv=(Invocable)engine;/get script object on which we want to call the method Object obj=engine.get(obj);/invoke the method named hello on the script object obj inv.invokeMethod(obj,hello,Script Method!);3.5 在脚本中插入 Java 接口 相比从 Java用特定的脚本函数,有候使用脚本函数或方法调时实现 Java 接口会得非常变方便。而且,由于使用了借口,在很多合可以回避使用场javax.script API。取得接口的目,就可以用各各的实现标调种样Java API。在下面的例子中,里这将演示一个 java.lang.Runnable 接口的。实现public class RunnableImpl public static void main(String args)throws Exception ScriptEngineManager manager=new ScriptEngineManager();ScriptEngine engine=manager.getEngineByName(JavaScript);/JavaScript code in a String String script=function run()println(run called);/evaluate script engine.eval(script);Invocable inv=(Invocable)engine;/get Runnable interface object from engine.This interface methods /are implemented by script functions with the matching name.Runnable r=inv.getInterface(Runnable.class);/start a new thread that runs the script implemented /runnable interface Thread th=new Thread(r);th.start();如果脚本言是基于目语标即目指向的情况,可以通脚本目使用脚本方法来装标过标时J 实 va 接口。根据一点,用接这调口方法的脚本全局函数得没有必要。脚本目可以封装接口方的系“状”。变标实现关态import javax.script.*;public class RunnableImplObject public static void main(String args)throws Exception ScriptEngineManager manager=new ScriptEngineManager();ScriptEngine engine=manager.getEngineByName(JavaScript);/JavaScript code in a String String script=var obj=new Object();obj.run=function()println(run method called);/evaluate script engine.eval(script);/get script object on which we want to implement the interface with Object obj=engine.get(obj);Invocable inv=(Invocable)engine;/get Runnable interface object from engine.This interface methods /are implemented by script methods of object obj Runnable r=inv.getInterface(obj,Runnable.class);/start a new thread that runs the script implemented /runnable interface Thread th=new Thread(r);th.start();3.6 多重域的脚本 在脚本量的例子中,解了如何将程序目作脚本全局量公的方法。通它可以将目公到脚本的多全局变讲标为变开过标开项域scopes中。如果是一域,需要单则javax.script.Bindings 接口。个接口承自这继java.util.Map。域是一个“键-”映射,不能是值键null 或空的文字串。多重的域被(脚本上下文)javax.script.ScriptContext 接口支持。脚本上下文(Script Context)支持一个或多个相的域。默情况下,关联捆绑认一个脚本引擎都附一个脚本上下文。默脚本上下文至少有一个被称之“每带认为ENGINE_SCOPE”的域。各各的域被种样脚本上下文支持,并且可以通过 getScopes 方法来提取。import javax.script.*;public class MultiScopes public static void main(String args)throws Exception ScriptEngineManager manager=new ScriptEngineManager();ScriptEngine engine=manager.getEngineByName(JavaScript);engine.put(x,hello);/print global variable x engine.eval(println(x););/the above line prints hello /Now,pass a different script context ScriptContext newContext=new SimpleScriptContext();Bindings engineScope=newContext.getBindings(ScriptContext.ENGINE_SCOPE);/add new variable x to the new engineScope engineScope.put(x,world);/execute the same script-but this time pass a different script context engine.eval(println(x);,newContext);/the above line prints world 4 JavaScript 脚本引擎 Sun 在 JDK6 中了与实现Mozilla Rhino 的 JavaScript 脚本引擎的相互。本捆绑样Mozilla Rhino 的版本是 1.6R2。大多数 Rhino都被入近来。但是,实现镶考到虑尺寸和安全因素,有几个控件被排除在外,如下:1.从 JavaScript到编译2制功能进码(也被称为化器优)。此特性依存于生成函数。除此特性意味着类库删JavaScript 将是被。除此特性并不会影到脚本的行,因化器是被透明化的。总编译删响执为优2.Rhino 的 JavaAdapter 被除。删JavaAdapter 是 JavaScript 用来通展过扩Java来类实现 Java 接口功能的技能。依照 Sun 的方法,可以用 JavaScript 目来一个标实现Java 借口。所以下面的代片断就会如期的那码你预样运行:var v=new java.lang.Runnable()run:function()print(hello);v.run();3.大多数情况下,JavaAdapter 就像使用 Java 匿名一被筑一个一的接口装。用类样构单实JavaAdapter 来展扩Java或者数个接口类实现的情况是非常少的。4.不包含 Rhino 命令行工具(被用于 Rhino shell、等调试),但是可以使用 jrunscript。5 从JavaScript 到Java的通讯 访问 Java、目以及方法是非常的。特是从类标简单别JavaScript字段和方法,访问这跟从 Java一的。在里访问时样这将明从说JavaScript 访问 Java 的一些重要的方面,如果想要了解更多有方面的信息,清关这访问http:/www.mozilla.org/rhino/scriptjava.html。下一个例子是访问 Java 的一个 JavaScript 小片断。部分需要一这定的 JavaScript 知。如果只识你对 JavaScript 之外的 JSR-223准脚本言感趣,可以跳一。标语兴过这节5 5.1.1 插入插入 JavaJava的包、类的包、类 了入为导Java 包和,可以使用入函数类镶importPackage 和 importClass。/Import Java packages and classes/like import package.*;in JavaimportPackage(java.awt);/like import java.awt.Frame in JavaimportClass(java.awt.Frame);/Create Java Objects by new ClassNamevar frame=new java.awt.Frame(hello);/Call Java public methods from scriptframe.setVisible(true);/Access JavaBean properties like fieldsprint(frame.title);如果使用了 Packages 全局量,就可以变访问 Java 包。例如:Packages.java.util.Vector、Packages.javax.swing.JFrame。“java”是“Packages.java”的快捷方式。javax、org、edu、com、net些前都是相的快捷方式,所以,上所有的这词语缀应实际JDK用平台的累都可以省应去“Packages”接来。头词访问/create JavaImporter with specific packages and classes to importvar SwingGui=new JavaImporter(javax.swing,javax.swing.event,javax.swing.border,java.awt.event);with(SwingGui)/within this with statement,we can access Swing and AWT /classes by unqualified(simple)names.var mybutton=new JButton(test);var myframe=new JFrame(test);5.2 声明和使用 Java 数组 然声明虽Java 目的方式跟标Java 相同,但是,在 JavaScript 中声明 Java 数需要明组则确 Java 映射。不,过Java 数组一旦被声明之后,于元素和度的就跟对长访问Java 相同了。有,如果一个还Java 方法被期待返回一个 Java 数,那组,脚本数可以被直接使用么组(自动转换)。所以,很多情况下是没有必要特声明一个别Java 数的。组/create Java String array of 5 elementsvar a=java.lang.reflect.Array.newInstance(java.lang.String,5);/Accessing elements and length access is by usual Java syntaxa0=scripting is great!;print(a.length);5.3 实现Java 接口 依照 Java 匿名的使用方法,在类JavaScript 中可以一个实现Java 接口。var r =new java.lang.Runnable()run:function()print(running.n);/r can be passed to Java methods that expect java.lang.Runnablevar th=new java.lang.Thread(r);th.start();如果一个接口只有一个一方法,可以直接入脚本函数单带(自动转换)。function func()print(I am func!);/pass script function for java.lang.Runnable argumentvar th=new java.lang.Thread(func);th.start();5.4 解决重载 Java 方法可以根据参数型的不同行重。重在进载载Java 的编译(行运javac 命令)程中得到解决。当用脚本从代中过调码用调Java 方法,脚本解器时释/器必一个恰当的方法。在编译须选择JavaScript 引擎中,不需要做一些特的理,因别处正的为确Java 方法重体是通参数型来的。但是,也有需要声明载变过选择选择(或者有必要说)特定重体的情况。载变var out=java.lang.System.out;/select a particular println function outprintln(java.lang.Object)(hello);于在关JavaScript 中解决 Java 方法重的其他信息参考此地载详细请址。http:/www.mozilla.org/js/liveconnect/lc3_method_overloading.html6 自己的脚本引擎实现 自己的脚本引擎实现,需要实现 javax.script.ScriptEngine 和 javax.script.ScriptEngineFactory 借口是必要条件。抽象类 javax.script.AbstractScriptEngine 将提供于实现ScriptEngine 接口的几个有用的方法。在始开实现 JSR-223 引擎之前,可能会想要一下你确认http:/ JSR-223准的脚本引擎,在里不作标这做明。细说7 参考料资 Java Scripting Programmer s Guide (此文档的英文原文)JSR-223 Scripting for the Java Platform JavaScript Developer Connection Java Method Overloading and LiveConnect 3 Rhino:JavaScript for Java Scripting Java(from JavaScript) project 8 译注 如何体在验如何体在验JavaJava上行运上行运JavaScript?JavaScript?里有相的源?哪应码里有相的源?哪应码 如果对 Java 脚本言感趣,而且,自己的上先安装语兴你电脑JDK6 可以从$JAVA_HOME/sample/scripting 中看到一个Sun 的 scriptpad 小工具。在$JAVA_HOME/sample/scripting/scriptpad 下有 build.xml。用 ant 就可以、配置个编译这小工具了。于个小工具其他信息可以参考关这详细scriptpad 目下的录README 文档。并配置后编译ant 会自生成动build 目,下面有一个录scriptpad.jar 文件。是一个可以行这执JavaScript 的小工具。目录 src 中是个工具的代,这码build/classes 是后的代。编译码其他的信息详细请浏览 README.txt 文件内容。
展开阅读全文