写点什么

使用 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

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

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

关注

评论

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

基于Casbin的ABAC授权模型设计与开发踩坑实录

天翼云开发者社区

安全 权限管理 访问控制

DeepSeek-R1源码解读

AI布道Mr.Jin

JVM内存结构33连问

量贩潮汐·WholesaleTide

JVM

图纸太杂乱?1秒关闭CAD图层,清爽看图!

在路上

cad cad看图 cad图纸

flstudio找不到中文设置,没有语言选项怎么办?FL Studio设置中文教程,FL Studio中文版免费下载

阿拉灯神丁

编曲软件 FL Studio 水果FL Studio FL水果 音乐创作

2025年面试通过率低?来看看一位Android大牛的BAT面试心得与经验总结

程序员每日分享

程序员 面试 移动开发 Android开发 互联网大厂

向量删除的3种方式

DashVector

人工智能 数据库 大模型

从电脑到座舱:英特尔携AI科技杀入智能汽车主战场

科技热闻

编程助手怎么选?我都要!左手通义灵码,右手 Cursor,组合来用超级爽

阿里巴巴云原生

阿里云 通义灵码

西南会议 | 2025 Altair 区域技术交流会下周五成都,日程+演讲阵容+惊喜好礼全面公布!

Altair RapidMiner

人工智能 AI 仿真 CAE AI驱动工程

HDC 2025|在AppGallery发现精品应用

最新动态

AppGallery Connect(AGC)账号与权限管理体系

小赵学鸿蒙

商务 AppGallery Connect 鸿蒙开发工具

2025年含泪狂刷Android基础面试118题,offer拿到手软

程序员每日分享

程序员 面试 移动开发 Android开发 互联网大厂

编程助手怎么选?我都要!左手通义灵码,右手 Cursor,组合来用超级爽

阿里云云效

阿里云 通义灵码

用DeepSeek+ Python 自动生成测试用例 狂省5小时,漏测率暴降83%!

测试人

人工智能

开源鸿蒙亮相HDC 2025 共建千行万业的数字底座

最新动态

上海人工智能实验室明珠湖会议首开,解答AI前沿疑问,推进科学智能

ModelWhale

科学智能 上海人工智能实验室 明珠湖会议

微信读书十周年,后台架构的技术演进和实践总结

JackJiang

网络编程 即时通讯 IM

YMatrix 技术内幕:详解 10w+ TPS 背后的技术矩阵

YMatrix 超融合数据库

OLTP HTAP OLTP 场景实践 YMatrix HTAP数据库

面临秋招!卷S人的Java中高级核心知识全面解析面试手册,涨薪跳槽拿高薪靠它了!

程序员高级码农

Java 程序员‘

Java 集合框架底层数据结构实现深度解析

电子尖叫食人鱼

Java 数据结构

电子制造智能化转型:MES如何解决工艺复杂、质量追溯与供应链协同

万界星空科技

mes 万界星空科技mes 电子电器制造业 电子电器行业 电子行业mes

原点安全入选Gartner®“数据安全平台”中国市场指南代表厂商

原点安全

Java线程池详解:高效并发编程的核心利器

不在线第一只蜗牛

Java

PAI推理重磅发布模型权重服务,大幅降低冷启动与扩容时长

阿里云大数据AI技术

开源 扩容 冷启动 模型训练/测试 大型语言模型LLM

更强模型效果!豆包大模型 1.6 系列上线边缘大模型网关,最高申领1000万免费 Tokens

火山引擎边缘云

AI+ 端侧AI 大模型 侧端大模型

医学+AI系列第一场|聚焦北京中医药大学的产-教-研融合、以赛促学、创新驱动的人才培养实践

ModelWhale

以赛促学 北京中医药大学

爱测智能体测试平台·全新升级邀您体验

测试人

人工智能 软件测试

商场商圈潜客挖掘模型

天翼云开发者社区

数据挖掘 大数据

博大数据精彩亮相2025中国国际金融展,全栈解决方案赋能金融数字化升级

极客天地

等保测评费用谁出?收费依据是什么?

行云管家

等保 堡垒机 等保测评

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