阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

使用 Java Web Start 部署 JRuby 应用

  • 2008-04-02
  • 本文字数:4025 字

    阅读完需:约 13 分钟

你通常需要一个命令来进入 Ruby 和 Java 的联合世界:

include Java这使你可以实例化 Java 类,调用其方法,甚至继承它们,就好象它们仅仅是普通的 Ruby 对象一样。但这其中有一些微妙的差异,这篇文章将向你展示如何管理它们以便能以最快的速度设计出新的应用并部署到你的客户那里。

这篇文章基于一个简单的应用,该应用使用 JRuby 和 Swing 实现了一个简单的 ObjectSpace 浏览器。Ruby 的 ObjectSpace 特性提供了一种方式来访问系统中所有对象。例如,我们可以这样打印所有使用中的字符串:

ObjectSpace.each_object(String) do |string|<br></br> puts string<br></br>end当该程序在我的 irb 会话中运行时,大约会产生 28000 个字符串。通过使用 Swing 和 JRuby,我们可以把不同的类显示在一个非常棒的图形界面上,包括它们的实例以及可用的方法。你甚至可以在最右边的面板中点击它们来调用无参的方法:

JRuby 的 ObjectSpace 支持在默认情况下是被禁用的,这是由于它在运行时所产生的性能问题,当然还有其他原因。

我要指出它在实现中的一些有趣的细节,并就如何开始使用 JRuby 中的 Java 集成特性给出一些提示。

Java 集成

一旦你将 Java 集成到脚本中,你就可以继承现有的 Java 类。我们只需要通过指定 Java 类的完整限定名就可以做到这一点。在这个例子应用中,主窗口继承了 JFrame。该类中还包含进了 javax.swing 和 java.awt 包,所以你不必每次都使用类的全名。

class MainWindow < javax.swing.JFrame<br></br>include_package 'javax.swing'<br id="vdnl"></br>include_package 'java.awt' ...做为另外一种选择,你还可以使用 include_class 功能包含指定的类,这样就不会因你没有使用某些类,而污染了名称空间。

调用父类的构造方法就和普通的 Ruby 代码一样,这意味着我们可以在 initialize 方法的第一行通过调用 super(“JRuby Object Browser”) 来设定窗口的标题。

因为类包含了整个 javax.swing 包,所以实例化 Java 类就变得非常直接:

list_panel = JPanel.new<br></br>list_panel.layout = GridLayout.new(0, 3)如果你仔细看看第二行,你可能会觉得我们直接访问了 JPanel 的 layout 属性,但事实并非如此。JRuby 为 Java 对象增加了一些便捷的方法,所以上面的语句也可以用我们熟知的方式编写:

list_panel.setLayout(GridLayout.new(0, 3))不再使用 getters 和 setters,看起来你可以直接访问属性。JRuby 还向 Java 对象增加了更多的“语法糖”,这使得整个感觉更像 Ruby 了:对于任何方法调用,你可以使用 snake_case 符号而不是为任何方法调用而实际定义的 camel case 名。由此产生出调用 setLayout 方法的第三种方式:

list_panel.set_layout(GridLayout.new(0, 3))从类中调用 setter 方法时要小心,Ruby 可能会认为你想创建一个局部变量,所以你必须以 self 作为接收者来显式地调用它:

self.default_close_operation = WindowConstants::EXIT_ON_CLOSEJava 和 Ruby 的另一个区别是对于常量的访问,像之前代码片断中的 EXIT_ON_CLOSE。记住,当你将 Java 代码转化为 Ruby 时,要将所有的. 访问符替换为::。

到目前为止,JRuby 对于 Swing 开发所带来的变化看起来好像也没什么,但是我们尚未涉及到一个非常重要的方面:监听器。在 Java 中,将一个监听器与事件关联起来通常需要在一个匿名类中实现一个接口:

button.addActionListener(new ActionListener() {<br></br>  public void actionPerformed(ActionEvent e) {<br id="v1-q"></br>  ... <br></br> } <br></br>});如果你想附加很多监听器时这很容易搞乱你的代码。在 JRuby 中,以下两行代码就能解决问题(如果你不使用 event 变量,你甚至可以忽略掉它):

button.add_action_listener do |event| <br></br> ... <br id="d8d9"></br>end这些是你使用 JRuby 开发 Swing 时需要掌握的基础。尽管 JRuby 使得用 Swing 开发 GUI 变得更方便,但是你还是需要手写很多代码,当需要复杂布局时更是如此。如果你希望能更简单地创建 Swing UI 时,请参考使用JRuby GUI APIs 的三种方式

部署JRuby 应用变得更简单

Ruby 应用和库通常是通过 RubyGems 分发的,但是为了利用其优势,你需要安装好 Ruby 和 RubyGems,而这对于一般的用户来说却并不实际。对于传统的(MRI / C-Ruby)程序,该问题已经通过 RubyScript2Exe[1] 的方式得到了解决,这是通过将脚本和一个 Ruby 解释器绑定到一个可运行在多个平台上的包里面来实现的。JRuby 的用户也不必为此感到沮丧,相反,他们手头上已经有了一个更加强大的工具来快速部署应用:Java Web Start。

使用 Java Web Start

Java Web Start 包含在 Java 运行时环境中,因此在大多数系统中都可以使用。使用 Web Start 部署应用相当简单,所需要的仅仅是一个包含所有文件和 JNLP(Java Network Launching Protocol)描述文件的 jar 包。我们在 ObjectSpace 浏览器应用的基础上,来示范一下如何创建一个可以通过 web-start 进行部署的 Ruby 应用。

使用 Web Start 的前提是一个包含应用的 jar 包,我们首先从它开始。JRuby 提供了两种不同的库:“最小的”jruby.jar 和 jruby-complete.jar,后者捆绑了整个 Ruby 标准库。如果你不使用标准库,那么你可以使用更小的 jruby.jar,这样可以减少大约 1M 的下载量。

让你的脚本运行的最简单的方式就是将.rb 文件添加到 jruby.jar。下面的命令将我们例子中的 rob.rb 增加到压缩包中。

jar uf jruby.jar rob.rb你可以通过 java 来启动应用,来检查上面的命令是否正确,而这需要我们的 Ruby 脚本。这个应用程序需要 ObjectSpace,我们可以通过向 Java 传递 jruby.objectspace.enabled=true 属性来激活它。

java -Djruby.objectspace.enabled=true -jar jruby.jar -r rob-r 选项自动寻找所需文件,然后运行我们的脚本。

提早编译

JRuby1.1 的一个令人激动的新特性就是对提前(ahead of time,即 AOT)编译的支持。现在 JRuby 中有 2048 个方法采用即时编译,而提前编译能减轻这一限制。JRuby 编译器jrubyc 目前仍处在开发中,所以我建议使用最新的JRuby 版本。将普通的Ruby 文件编译为class 文件就像通过脚本参数调用编译器那样简单:

jrubyc rob.rb这会创建一个包含 rob.class 文件的 ruby 目录。这次不再需要像我们之前那样将 ruby 目录打包到 jruby.jar 中,而只需要创建一个单独的 Jar 来包含应用程序。毕竟修改现存的 Jar 看起来并不是一个优雅的方案。我们可以使用同名的工具来创建 Jar:

jar -cfe rob.jar ruby/rob.class ruby这会创建一个包含我们的类的名为 rob.jar 的小的 jar 文件,并且在 Manifest 中指定 ruby/rob.class 为主类。这使得我们可以简化调用,因为我们现在可以很简单地指向类,而无需使用命令行。为了执行它,我们要确保 rob.jar 在 classpath 上:

java -Djruby.objectspace.enabled=true -cp rob.jar:jruby.jar ruby.rob#### Web Start

在我们继续编写 JNLP 文件前,我们需要对 Jars 进行签名。很不幸需要这么做,因为 JRuby 使用了反射,这样就需要更多的许可,你可以参阅 JRuby Wiki 来了解更多的细节。最简单的方法就是使用 JDK 自带的 keytool 来创建一个测试证书。

keytool -genkey -keystore myKeystore -alias myself<br></br>keytool -selfcert -alias myself -keystore myKeystore从现在开始,每次你修改 Jars 时,必须要更新签名,否则在运行时你就会得到一个 SecurityException。

jarsigner -keystore myKeystore jruby.jar myself<br></br>jarsigner -keystore myKeystore rob.jar myself既然我们已经准备好 Jars 了,我们就来看一下 JNLP 文件。下面提供了对应用的一个最小配置。一些字段是规范要求的,比如 title、vendor、j2se 标签以及 security 段。jar 标签代表了 Jars 的最终位置。它还可以使用 file:// 形式的 URL 指向本地文件,在开发中这会很方便。ObjectSpace 属性也需要在此设定,这可以通过 property 标签来完成。

<br></br><jnlp><p><information><p><vendor>Mirko Stocker</vendor></p></information><resources><br></br><jar href="http://misto.ch/rob/rob.jar"><br></br><jar href="http://misto.ch/rob/jruby.jar"><br id="hx8y"></br><j2se version="1.5+"><br></br><property name="jruby.objectspace.enabled" value="true"><br></br></property><br></br><application-desc main-class="ruby.rob"><br id="o7ei"></br><security><br></br><all-permissions><br></br></all-permissions><br></br></security> </application-desc></j2se></jar></jar></resources></p></jnlp>如果你忽略了 AOT 段或者仅仅想使用单个 jar 的方式,那么你就必须修改 jnlp 文件并包含 -e 参数,那么你的 application-desc 看起来应该像这样:

[...]<p><application-desc><p><argument>-r</argument><argument>rob</argument></p></application-desc>[...]</p><br></br>最后一步是将 Jars 和 JNLP 文件上传到指定位置。现在你应该可以在浏览器或者使用 shell 中的 javaws 工具来打开链接了。

问题解决

为了让你的浏览器能通过 Web Start 加载应用,我们需要使用 application/x-java-jnlp-file MIME 类型来发布 JNLP 文件。因此如果你的浏览器仅仅显示了 JNLP 文件的内容并且 javaws 没有自动加载的话,你就需要改变 web 服务器的配置。例如,Apache 需要在 mime.types 中增加如下指令:

application/x-java-jnlp-file jnlp### 进一步阅读

JRuby wiki 提供了关于 JRuby 的很多信息

  1. http://www.erikveen.dds.nl/rubyscript2exe/

下载 code for Ruby Object Browser

查看英文原文: Deploying JRuby applications with Java Web Star


译者简介:张龙,同济大学软件工程硕士,现就职于理光软件研究所。主要从事文档工作流和办公自动化解决方案的研发工作。热衷于 Java 轻量级框架的研究,对敏捷方法很感兴趣。曾有若干年的 J2EE 培训讲师经历。参与 InfoQ 中文站内容建设,请邮件至 china-editorial[at]infoq.com

公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2008-04-02 04:172713
用户头像

发布了 88 篇内容, 共 258.5 次阅读, 收获喜欢 8 次。

关注

评论

发布
暂无评论
发现更多内容

架构师训练营第 3 周——学习总结

在野

极客大学架构师训练营

第三周作业

戴维斯

极客大学架构师训练营

【week03】总结

chengjing

架构师训练营第三周课后作业

竹森先生

极客大学架构师训练营

万恶的NPE差点让我半个月工资没了

java金融

Java 程序员 互联网 NPE 空指针

奈学教育《大数据开发工程师》课程大纲

古月木易

大数据

瓷都景德镇牵手蚂蚁区块链,重塑非遗陶瓷产业

CECBC

区块链技术 溯源 防篡改 景德镇 非遗

架构师训练营第 3 周 _ 学习总结

方舟勇士

课程总结

大白话Java多线程,小白都能看的懂的哦

java金融

Java 多线程 线程安全 创建线程方式 什么是多线程

【架构师训练营 - 周总结 -3】设计模式、重构

小动物

总结 极客大学架构师训练营 第三周

第三周作业

andy

【week03】作业1

chengjing

架构师训练营Week03

Frank Zeng

第三周作业

芒夏

极客大学架构师训练营

奈学教育《百万架构师》课程大纲

古月木易

极客大学架构师训练营

到底是什么让IT人如此苦逼???

纯洁的微笑

程序员 程序人生

用于可视化软件体系结构的C4模型(转载)

清风徐徐

奈学教育《百万架构师》课程大纲

奈学教育

极客大学架构师训练营

第三周总结

andy

中心化是人性,去中心化是技术

CECBC

区块链技术 去中心化 超级节点

从单机事务到分布式事务

ElvinYang

代码重构练习三

极客李

有益思考一则:概率与格局

石君

思考 思维方式 格局

week3 学习总结

不在调上

极客大学架构师训练营

【架构师训练营 - 作业 -3】组合模式

小动物

极客大学架构师训练营 作业 第三周

Tweak原理与越狱防护

冯选刚

单例和组合模式

陈皮

8行代码的21问题: 如何有效Code Review?

zzj8704

Code Review 代码规范 可测性 CR常见规则 结构化CR

当教育遇上区块链,会擦出什么样的火花?

CECBC

区块链技术 去中心化 防篡改 教育资源共享

元年云“宽能力”拓宽成长型企业数字化升级之路

人称T客

week3 作业& 手撕单例模式

不在调上

使用Java Web Start部署JRuby应用_Java_Mirko Stocker_InfoQ精选文章