上海:15201841284
广州:020-2989 6995
深圳:0755-23061965
武汉:027-8798 9193
西安:029-8822 8155
脚本语言的一些有用的特性是:
更多精彩内容以及学习资料,尚学堂论坛bbs.bjsxt.com免费下载。
Java 脚本 API 是一种独立于框架的脚本语言,使用来自于Java代码的脚本引擎 。通过java脚本API,可以使用Java语言编写定制/可扩展的应用程序并将自定义脚本语言选择留给最终用户 。Java 应用程序开发者不需要在开发过程中选择扩展语言。如果你使用JSR-223 API来编写应用,那么你的用户可以使用任何JSR-223兼容的脚本语言。
Java 脚本功能是在 javax.script 包中。这是一个比较小的,简单的API。脚本的出发点是 ScriptEngineManager 类。一个 ScriptEngineManager 对象可以通过jar文件的服务发现机制发现脚本引擎。它也可以实例化脚本引擎来解释使用特定的脚本语言编写的脚本。使用脚本编程接口的最简单的方法如下:
ScriptEngineManager
对象ScriptEngineManager
获取 ScriptEngine
对象ScriptEngine的eval方法执行脚本
现在,是时候看一些样本代码了。了解一些JavaScript有助于阅读这些例子,但不是强制的。
从ScriptEngineManager实例中,我们通过 getEngineByName
方法得到一个JavaScript引擎实例。通过脚本引擎的eval方法来执行给定的JavaScript代码。为简便起见,本例以及随后的例子中,我们不对异常进行处理。javax.script API有检查和运行时异常,你必须妥善处理异常。
import javax.script.*; public class EvalScript { public static void main(String[] args) throws Exception { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("JavaScript"); engine.eval("print('Hello, World')"); } }
在这个例子中,我们调用eval方法来接收java.io.Reader作为输入源。读入的脚本被执行。这种方式能够成文件执行脚本,用相关的输入流对象读取URL和资源。
import javax.script.*; public class EvalFile { public static void main(String[] args) throws Exception { ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("JavaScript"); engine.eval(new java.io.FileReader(args[0])); } }
假设我们有一个叫"test.js"的文件,里面的内容如下:
println("This is hello from test.js")
我们可以使用下面的方式来运行刚刚的脚本
java EvalFile test.js
当你的java应用程序嵌入脚本引擎和脚本,你可能希望将您的应用程序对象为全局变量暴露于脚本中。这个例子演示了如何将您的应用程序对象作为全局变量暴露于脚本中。我们在应用程序中创建一个 java.io.File对象作为全局变量,名称是file。该脚本可以访问变量,例如,它可以调用它的公共方法。注意访问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"); engine.put("file", f); engine.eval("print(file.getAbsolutePath())"); } }
有些时候,你可能需要多次调用一个特定脚本函数,例如你的应用程序菜单功能可能由脚本来实现。在菜单中的操作事件处理程序中,可能需要调用一个特定的脚本函数。下面的示例演示在Java代码调用一个特定的脚本。
import javax.script.*; public class InvokeScriptFunction { public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); String script = "function hello(name) { print('Hello, ' + name); }"; engine.eval(script); Invocable inv = (Invocable) engine; 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"); String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }"; engine.eval(script); Invocable inv = (Invocable) engine; Object obj = engine.get("obj"); inv.invokeMethod(obj, "hello", "Script Method !!" ); } }
有些时候通过脚本函数或者方法可以很方便的实现java接口,而不是在Java中调用。同时,通过接口我们可以避免在很多地方使用javax.script API接口。我们可以得到一个接口实现者对象并将其传递给不同的Java api。下面的例子演示了通过脚本实现 java.lang.Runnable接口。
import javax.script.*; public class RunnableImpl { public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); String script = "function run() { println('run called'); }"; engine.eval(script); Invocable inv = (Invocable) engine; Runnable r = inv.getInterface(Runnable.class); Thread th = new Thread(r); th.start(); } }
如果你的脚本语言是基于对象或者面向对象的,可以通过脚本对象的脚本方法来实现Java接口。这避免了不得不调用脚本全局函数的接口方法。脚本对象可以存储接口实现状态。
import javax.script.*; public class RunnableImplObject { public static void main(String[] args) throws Exception { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); String script = "var obj = new Object(); obj.run = function() { println('run method called'); }"; engine.eval(script); Object obj = engine.get("obj"); Invocable inv = (Invocable) engine; Runnable r = inv.getInterface(obj, Runnable.class); Thread th = new Thread(r); th.start(); } }
在 script variables 例子中,我们看到怎样将应用对象暴露为脚本的全局变量。它有可能暴露为多个全局的作用域 。 单作用域是javax.script.Bindings的实例中
. 这个借口派生至java.util.Map
scope 键值对的集合,其中键为非空、非空字符串。 多scopes 是 javax.script.ScriptContext
接口支持的。支持一个或多个脚本上下文与相关的域绑定。默认情况下, 每一个脚本引擎都有一个默认的脚本上下文。 默认的脚本上下文有至少一个域叫 "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"); engine.eval("println(x);"); ScriptContext newContext = new SimpleScriptContext(); Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE); engineScope.put("x", "world"); engine.eval("println(x);", newContext); } }
Sun的JDK 6中包含了一个基于 Mozilla Rhino JavaScript 脚本引擎。 这个引擎是基于版本为1.6R2的Mozilla Rhino 。多数 Rhino 实现都被包含在内。少部分组件由于大小和安全原因被排除了:
var v = new java.lang.Runnable() { run: function() { print('hello'); } } v.run();
在大多数情况下,JavaAdapter是采用匿名类语法来实现单接口。 使用JavaAdapter来扩展Java类或实现多接口并不常见。
在大多数情况下,访问Java类、对象和方法很简单。从JavaScript中访问属性和方法与同Java中一样。这里,我们突出JavaScript Java访问的重要方面.。更多的细节请阅读https://www.mozilla.org/rhino/scriptjava.html。下面是一些JavaScript访问Java的代码片段。本节需要一些JavaScript知识。如果你打算使用JSR-223中非JavaScript脚本语言,那么本节可以跳过。
内置的函数importPackage
和importClass
可以用于引入Java 包和类。
importPackage(java.awt); importClass(java.awt.Frame); var frame = new java.awt.Frame("hello"); frame.setVisible(true); print(frame.title);
全局变量Packages也可以用于访问Java包。例如: Packages.java.util.Vector
, Packages.javax.swing.JFrame
. 请注意: "java" 是 "Packages.java"的快捷引用。还有一些等价的快捷引用前缀 : javax, org, edu, com, net, 所以几乎所有的 JDK 平台下的类都可以不使用"Packages" 前缀而访问到。
请注意,java.lang不是默认引入的 (与Java不同),因为会与 JavaScript's 内置的 Object, Boolean, Math 等冲突。
importPackage
和importClass
函数"污染" 了JavaScript中的全局变量。为了避免这种情况,你可以使用JavaImporter。
var SwingGui = new JavaImporter(javax.swing, javax.swing.event, javax.swing.border, java.awt.event); with (SwingGui) { var mybutton = new JButton("test"); var myframe = new JFrame("test"); }
在JavaScript中,创建一个对象时与Java中一样,而创建Java数组时需要显式的使用Java反射。但一旦创建好后,访问其中的元素或获取大小就和Java中一样。 另外,也可以使用脚本数组用在Java方法中期望的Java数组(因为可以自动转换)。所以在大多数情况下我们不需要显式地创建Java数组。
// create Java String array of 5 elements var a = java.lang.reflect.Array.newInstance(java.lang.String, 5); // Accessing elements and length access is by usual Java syntax a[0] = "scripting is great!"; print(a.length);
在JavaScript中,可以使用Java匿名类语法形式实现Java中接口:
var r = new java.lang.Runnable() { run: function() { print("running.../n"); } }; var th = new java.lang.Thread(r); th.start();
当接口中只有一个需要实现的方法时,你可以自己传入脚本的函数(因为可以自动转换)。
function func() { print("I am func!"); } var th = new java.lang.Thread(func); th.start();
Java方法是使用参数类型重载的。在Java中,重载发生在编译阶段 (执行 javac)。当脚本中调用Java方法时,脚本的翻译器或编译器需要选择适当的方法。对于JavaScript引擎,您不需要做任何特别的——正确的Java方法重载变体是根据参数类型选择的。 但有时,您可能希望(或有)显式地选择一个特定的过载变体。
var out = java.lang.System.out; // select a particular println function out["println(java.lang.Object)"]("hello");
更多精彩内容以及学习资料,尚学堂论坛bbs.bjsxt.com免费下载。
北京京南校区:北京亦庄经济开发区科创十四街6号院1号楼 赛蒂国际工业园
咨询电话:400-009-1906 / 010-56233821
面授课程: JavaEE+微服务+大数据 大数据+机器学习+平台架构 Python+数据分析+机器学习 人工智能+模式识别+强化学习 WEB前端+移动端+服务端渲染
地址:陕西省西安市高新区西安软件园西区创新信息大厦A座三层尚学堂
电话:029-88228155 / 18291433445
山西学区地址:山西省晋中市榆次区大学城大学生活广场万科商业A1座702
武汉学区地址:武汉市东湖高新区光谷金融港B22栋11楼
咨询电话:027-87989193
网址:http://www.cssxt.com/
咨询电话:0731-83072091
深圳校区地址:深圳市宝安区航城大道U8智造产业园U6栋3楼
咨询电话:0755-23061965 / 18898413781
上海尚学堂校区地址:上海市浦东新区城丰路650号
咨询电话:021-67690939
广州校区地址:广州市天河区车陂街道大岗路5号中侨广场2栋321室(四号线车陂站D出口,或brt车陂站)
咨询电话:18948349646
保定招生办公室
地址:河北省保定市竞秀区朝阳南大街777号鸿悦国际1101室
电话:15132423123