- 浏览: 318482 次
- 性别:
- 来自: 长沙
文章分类
最新评论
-
完善自我:
支持一下!
揭秘IT人才特点:中美印日四国程序员比较 -
悲剧了:
好文,看玩thinking in java的提到的异常处理,看 ...
高效的Java异常处理框架(转) -
yin_bp:
开源框架bbossgroups页支持组件异步方法调用哦,详情请 ...
Spring 3中异步方法调用 -
flyjava:
sun的悲哀
Apache怒了,威胁说要离开JCP
现在,许多 Java 开发人员都喜欢在 Java 平台中使用脚本语言,但是使用编译到 Java 字节码中的动态语言有时是不可行的。在某些情况中,直接编写一个 Java 应用程序的脚本 部分 或者在一个脚本中调用特定的 Java 对象是更快捷、更高效的方法。
这就是 javax.script
产生的原因了。Java Scripting API 是从 Java 6 开始引入的,它填补了便捷的小脚本语言和健壮的 Java 生态系统之间的鸿沟。通过使用 Java Scripting API,您就可以在您的 Java 代码中快速整合几乎所有的脚本语言,这使您能够在解决一些很小的问题时有更多可选择的方法。
1. 使用 jrunscript 执行 JavaScript
每一个新的 Java 平台发布都会带来新的命令行工具集,它们位于 JDK 的 bin 目录。Java 6 也一样,其中 jrunscript
便是 Java 平台工具集中的一个不小的补充。
设想一个编写命令行脚本进行性能监控的简单问题。这个工具将借用 jmap
(见本系列文章 前一篇文章 中的介绍),每 5 秒钟运行一个 Java 进程,从而了解进程的运行状况。一般情况下,我们会使用命令行 shell 脚本来完成这样的工作,但是这里的服务器应用程序部署在一些差别很大的平台上,包括 Windows® 和 Linux®。系统管理员将会发现编写能够同时运行在两个平台的 shell 脚本是很痛苦的。通常的做法是编写一个 Windows 批处理文件和一个 UNIX® shell 脚本,同时保证这两个文件同步更新。
但是,任何阅读过 The Pragmatic Programmer 的人都知道,这严重违反了 DRY (Don't Repeat Yourself) 原则,而且会产生许多缺陷和问题。我们真正希望的是编写一种与操作系统无关的脚本,它能够在所有的平台上运行。
当然,Java 语言是平台无关的,但是这里并不是需要使用 “系统” 语言的情况。我们需要的是一种脚本语言 — 如,JavaScript。
清单 1 显示的是我们所需要的简单 shell 脚本:
while (true) { echo("Hello, world!"); } |
由于经常与 Web 浏览器打交道,许多 Java 开发人员已经知道了 JavaScript(或 ECMAScript;JavaScript 是由 Netscape 开发的一种 ECMAScript 语言)。问题是,系统管理员要如何运行这个脚本?
当然,解决方法是 JDK 所带的 jrunscript
实用程序,如清单 2 所示:
C:\developerWorks\5things-scripting\code\jssrc>jrunscript periodic.js Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! Hello, world! ... |
注意,您也可以使用 for
循环按照指定的次数来循环执行这个脚本,然后才退出。基本上,jrunscript
能够让您执行 JavaScript 的所有操作。惟一不同的是它的运行环境不是浏览器,所以运行中不会有 DOM。因此,最顶层的函数和对象稍微有些不同。
因为 Java 6 将 Rhino ECMAScript 引擎作为 JDK 的一部分,jrunscript
可以执行任何传递给它的 ECMAScript 代码,不管是一个文件(如此处所示)或是在更加交互式的 REPL(“Read-Evaluate-Print-Loop”)shell 环境。运行 jrunscript
就可以访问 REPL shell。
能够编写 JavaScript/ECMAScript 代码是非常好的,但是我们不希望被迫重新编译我们在 Java 语言中使用的所有代码 — 这是违背我们初衷的。幸好,所有使用 Java Scripting API 引擎的代码都完全能够访问整个 Java 生态系统,因为本质上一切代码都还是 Java 字节码。所以,回到我们之前的问题,我们可以在 Java 平台上使用传统的 Runtime.exec()
调用来启动进程,如清单 3 所示:
var p = java.lang.Runtime.getRuntime().exec("jmap", [ "-histo", arguments[0] ]) p.waitFor() |
数组 arguments
是指向传递到这个函数参数的 ECMAScript 标准内置引用。在最顶层的脚本环境中,则是传递给脚本本身的的参数数组(命令行参数)。所以,在清单 3 中,这个脚本预期接收一个参数,该参数包含要映射的 Java 进程的 VMID。
除此之外,我们可以利用本身为一个 Java 类的 jmap
,然后直接调用它的 main()
方法,如清单 4 所示。有了这个方法,我们不需要 “传输” Process
对象的 in/out/err
流。
var args = [ "-histo", arguments[0] ] Packages.sun.tools.jmap.JMap.main(args) |
Packages
语法是一个 Rhino ECMAScript 标识,它指向已经 Rhino 内创建的位于核心 java.*
包之外的 Java 包。
从脚本调用 Java 对象仅仅完成了一半的工作:Java 脚本环境也提供了从 Java 代码调用脚本的功能。这只需要实例化一个 ScriptEngine
对象,然后加载和评估脚本,如清单 5 所示:
import java.io.*; import javax.script.*; public class App { public static void main(String[] args) { try { ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript"); for (String arg : args) { FileReader fr = new FileReader(arg); engine.eval(fr); } } catch(IOException ioEx) { ioEx.printStackTrace(); } catch(ScriptException scrEx) { scrEx.printStackTrace(); } } } |
eval()
方法也可以直接操作一个 String
,所以这个脚本不一定必须是文件系统的一个文件 — 它可以来自于数据库、用户输入,或者甚至可以基于环境和用户操作在应用程序中生成。
仅仅调用一个脚本还不够:脚本通常会与 Java 环境中创建的对象进行交互。这时,Java 主机环境必须创建一些对象并将它们绑定,这样脚本就可以很容易找到和使用这些对象。这个过程是 ScriptContext
对象的任务,如清单 6 所示:
import java.io.*; import javax.script.*; public class App { public static void main(String[] args) { try { ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript"); for (String arg : args) { Bindings bindings = new SimpleBindings(); bindings.put("author", new Person("Ted", "Neward", 39)); bindings.put("title", "5 Things You Didn't Know"); FileReader fr = new FileReader(arg); engine.eval(fr, bindings); } } catch(IOException ioEx) { ioEx.printStackTrace(); } catch(ScriptException scrEx) { scrEx.printStackTrace(); } } } |
访问所绑定的对象很简单 — 所绑定对象的名称是作为全局命名空间引入到脚本的,所以在 Rhino 中使用 Person
很简单,如清单 7 所示:
println("Hello from inside scripting!") println("author.firstName = " + author.firstName) |
您可以看到,JavaBeans 样式的属性被简化为使用名称直接访问,这就好像它们是字段一样。
脚本语言的缺点一直存在于性能方面。其中的原因是,大多数情况下脚本语言是 “即时” 解译的,因而它在执行时会损失一些解析和验证文本的时间和 CPU 周期。运行在 JVM 的许多脚本语言最终会将接收的代码转换为 Java 字节码,至少在脚本被第一次解析和验证时进行转换;在 Java 程序关闭时,这些即时编译的代码会消失。将频繁使用的脚本保持为字节码形式可以帮助提升可观的性能。
我们可以以一种很自然和有意义的方法使用 Java Scripting API。如果返回的 ScriptEngine
实现了 Compilable
接口,那么这个接口所编译的方法可用于将脚本(以一个 String
或一个 Reader
传递过来的)编译为一个 CompiledScript
实例,然后它可用于在 eval()
方法中使用不同的绑定重复地处理编译后的代码,如清单 8 所示:
import java.io.*; import javax.script.*; public class App { public static void main(String[] args) { try { ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript"); for (String arg : args) { Bindings bindings = new SimpleBindings(); bindings.put("author", new Person("Ted", "Neward", 39)); bindings.put("title", "5 Things You Didn't Know"); FileReader fr = new FileReader(arg); if (engine instanceof Compilable) { System.out.println("Compiling...."); Compilable compEngine = (Compilable)engine; CompiledScript cs = compEngine.compile(fr); cs.eval(bindings); } else engine.eval(fr, bindings); } } catch(IOException ioEx) { ioEx.printStackTrace(); } catch(ScriptException scrEx) { scrEx.printStackTrace(); } } } |
在大多数情况中,CompiledScript
实例需要存储在一个长时间存储中(例如,servlet-context
),这样才能避免一次次地重复编译相同的脚本。然而,如果脚本发生变化,您就需要创建一个新的 CompiledScript
来反映这个变化;一旦编译完成,CompiledScript
就不再执行原始的脚本文件内容。
Java Scripting API 在扩展 Java 程序的范围和功能方面前进了很大一步,并且它将脚本语言的编码效率的优势带到 Java 环境。jrunscript
— 它显然不是很难编写的程序 — 以及 javax.script
给 Java 开发人员带来了诸如 Ruby (JRuby) 和 ECMAScript (Rhino) 等脚本语言的优势,同时还不会破坏 Java 环境的生态系统和可扩展性。
原文:http://www.ibm.com/developerworks/cn/java/j-5things9.html?ca=drs-tp4608
发表评论
-
Java包导入机制的解析总结
2010-12-01 20:50 1195java中有两种包的导 ... -
提高JSP和SERVLET性能的七大绝招
2010-11-30 10:02 1166本文讲述了调整JSP和servlet的一些非常实用的方法,它可 ... -
使用future实现内置异步API
2010-11-16 15:52 1056当设计并发策略时,要将 "what做什么" ... -
asyn4j—java 异步方法调用框架
2010-11-16 15:36 2093asyn4j 是一个java异步方法调用框架,包括 ... -
关于 Java 性能监控您不知道的 5 件事,第 2 部分
2010-11-15 11:02 767全功能内置分析器,如 JConsole 和 VisualVM ... -
关于 Java 性能监控您不知道的 5 件事,第 1 部分
2010-11-15 10:13 803当应用程序性能受到损 ... -
jsp生成静态页(jsp+servlet+xml)
2010-11-08 17:38 1327package ningxia.bl.admin.conten ... -
动态JSP页生成静态HTML
2010-11-08 17:31 1055具体实现: 利用 Filte ... -
深入Java核心 Java中多态的实现机制
2010-10-23 19:22 1218多态性是面向对 ... -
八个改善Java遗留系统的技巧
2010-10-16 10:04 819你没看错,就是这个题目:即使是Java系统也会变成“遗留”系统 ... -
IBM加入OpenJDK,和Oracle一道推动Java发展
2010-10-14 15:14 1662Oracle(新闻发布 )和IBM(新闻发布 )昨天联合宣 ... -
用 Slice 扩展 OpenJPA 应用程序
2010-10-11 09:43 1183简介 Slice 将 OpenJPA 扩展用 ... -
StAX API
2010-09-27 16:08 1256StAX API The StAX API expo ... -
常用 Java Profiling 工具的分析与比较
2010-09-26 17:10 1301简介: 在 Java 程序的 ... -
在Spring基础上实现自己的异常处理框架
2010-09-26 15:03 0应用项目大致的体系结 ... -
高效的Java异常处理框架(转)
2010-09-26 14:53 1545摘要:本文从Java异常最基本的概念、语法开始讲述了Jav ... -
关于 Java Database Connectivity 您不知道的 5 件事
2010-09-25 15:32 803目前,许多开发人员把 ... -
综述:字符串到Java对象转换的工具库(转)
2010-09-20 21:41 1118原文:http://www.infoq.com/cn/news ...
相关推荐
SAP GUI Scripting API for the Windows and Java Platforms
The SAP GUI Scripting API is an automation interface that enhances the capabilities of SAP GUI for Windows. Using this interface, end users may automate repetitive tasks by recording and running macro...
本资源主要介绍了 Java 平台标准版的脚本编程指南,旨在帮助开发者更好地使用 Java Scripting API 实现自动化和集成任务。下面是对资源的详细解读: 脚本编程概念 Java Scripting API 是 Java 平台标准版的一部分...
Java Scripting API是Java平台标准版的一部分,允许开发人员在Java应用程序中嵌入脚本语言。该指南将详细介绍Java Scripting API的使用、脚本引擎、脚本上下文、脚本变量、脚本执行、脚本安全等方面的知识点。 Java...
java.lang.reflect 提供类和接口,以获得关于类和对象的反射信息。 java.math 提供用于执行任意精度整数算法 (BigInteger) 和任意精度小数算法 (BigDecimal) 的类。 java.net 为实现网络应用程序提供类。 java.nio ...
Java Scripting Programmer's Guide Java Scripting Programmer's Guide是Java Platform, Standard Edition的一部分,旨在帮助开发者使用Java scripting来实现复杂的应用程序。以下是Java Scripting Programmer's ...
脚本语言在现代软件开发中的应用越来越广泛,Java平台通过引入JSR 223(Java Scripting API)和JSR 433(Java Scripting for the JVM)使得在Java环境中使用脚本语言变得可能和方便。本书详细探讨了如何在Java应用...
总之,Java 6 API中文版对于任何Java开发者来说都是不可或缺的参考资料,无论是在开发新项目还是维护旧代码时,都能提供强大的帮助。通过深入理解并熟练运用Java 6 API,开发者可以编写出更高效、更可靠的代码。
Java 脚本 API,也称为 Java Scripting API,是Java平台标准版(Java SE)的一部分,它允许Java应用程序在运行时执行脚本语言代码。这个API在Java 6版本中得到了显著增强,为开发者提供了在Java程序中嵌入和执行脚本...
基于 Google V8 Javascript 引擎的 Java Scripting API (JSR223) 的实现。 Java 规范请求 (JSR) 223 通过定义标准框架和应用程序编程接口 (API) 来帮助开发人员集成 Java 技术和脚本语言,以执行以下操作: 从脚本...
Scripting in Java starts with the explanation of basic scripting concepts and mechanisms needed for implementating scripting languages on the Java platform. Next, it focuses on particular languages ...
8. **动态类型语言支持**:通过JSR 223(Java Scripting API),Java 7增加了对动态语言的支持,如Groovy、JavaScript等。 9. **改进的Swing组件**:Java 7对Swing组件进行了优化,提高了UI的响应速度和用户体验。 ...
SAP GUI Scripting API 用户手册开发文档是针对2023年最新版本的SAP GUI自动化工具的重要参考资料,旨在帮助开发者和系统管理员更好地利用API在Windows和Java平台上自动化SAP客户端的操作。API提供了丰富的对象和...
【Java API 6详解】 Java API 6,全称为Java Application Programming Interface的第六个主要版本,是Java开发历史上的一个重要里程碑。它在2006年发布,为开发者提供了大量新特性和改进,提升了Java平台的性能、...
在Java 6(J2SE 6)中,进一步增强了API,包括Swing组件的改进、动态代理、NIO.2(非阻塞I/O)、Scripting API、改进的XML处理和Java数据库连接(JDBC)4.0。动态代理允许在运行时创建符合特定接口的代理对象。NIO....
5. **Scripting API**:`javax.script`包的引入,允许Java应用程序利用各种脚本语言(如JavaScript、Ruby等)进行嵌入式脚本执行,促进了脚本语言与Java的交互。 6. **XML处理改进**:Java 6对XML处理API进行了优化...
1. **动态语言支持**:引入了JSR 223(Java Scripting API),允许在Java程序中嵌入和执行多种脚本语言,如JavaScript、Groovy等,提升了Java平台的灵活性。 2. **改进的编译器**:Java 6.0的javac编译器性能得到了...
JavaScripting 是一个专门为初学者设计的在线互动教程,旨在帮助学习者通过实践来掌握JavaScript编程语言。这个"javascripting-源码.rar"压缩包可能包含了整个教程的源代码,包括HTML、CSS和JavaScript文件,以及...
6. **脚本引擎**:JDK6.0引入了JSR 223,即Scripting for the Java Platform,允许在Java应用程序中嵌入和执行各种脚本语言,如JavaScript、Groovy等。 7. **改进的Swing组件**:Swing库在JDK6.0中得到增强,包括新...