`
DigitalSonic
  • 浏览: 216103 次
社区版块
存档分类
最新评论

当Ruby遇到Java,勇敢地跨越边界吧

阅读更多

1. 引言
2004年Ruby on Rails的横空出世让大家为之一惊,很多Java社区对它也投去关注的目光,现在RoR已经渐渐为人接受,被运用于不少实际项目之中,这也让本来不怎么吸引眼球的Ruby从角落里走了出来。不少开发者在试用了Ruby和RoR后产生了浓厚的兴趣,毕竟Ruby的语法是如此的有趣,Rails中的开发是如此的便捷,有时它替你安排好了一切,敲键盘就是了。
但Ruby毕竟和主流的Java/.Net还存在一定距离,比如开发者数量,受关注度等等。更关键的是它缺乏像Java那样的库支持,很多时候不得不自己动手“丰衣足食”。后来人们想到了要去跨越语言的边界,但做总是比想要难,好在出现了JRuby,在它的帮助下,这条边界已经不再不可逾越,所以勇敢地跨出第一步吧!

2. JRuby的Java集成
如何让Ruby与Java紧密地结合在一起呢?你可以在Ruby中引用Java类、Java原子类型、Java数组,实现Java接口,继承Java类;也可以在Java中使用Ruby的代码。其实一切都很简单,你需要的只是一点小小的魔法而已。

2.1. JRuby中调用Java
在接触JRuby前我使用过RJB(Ruby Java Bridge,http://rjb.rubyforge.org/),两者都提供在Ruby中调用Java的功能,仅在这点上来说,感觉它们差不多,其实JRuby的功能要强大的多。如果你只是想在Ruby中简单地调用一些Java代码,那可以考虑RJB。
要在JRuby中使用Java,先要声明程序中需要Java集成,有两种方法,一种用require 'java';另一种直接使用java::java.util.ArrayList这样的语法。无论是何种方法,都要保证所用的Java类在CLASSPATH中。

require 'java'

java::java.util.ArrayList

Java类的使用也有几种选择:

include_class "java.util.HashMap"
x = HashMap.new
x.put("foo","bar")

include_class("java.lang.String") {|pkg,name| "JString"}
y = JString.new "Hello, world"

如果类是在java、javax、org或者com包中的,那还可以直接引用它们。

JString = java.lang.String
y = JString.new "Hello, world"

你可以这样来调用System.out.println:

java.lang.System.out.println("Hello, world")

值得一提的是这里的”Hello, world”是Ruby的字符串,而非java.lang.String,JRuby会自动对一些类型进行转换,开发者无需自己动手。
在Java中,方法和变量都用fooBar这样的形式,而Ruby中则是foo_bar,显然在代码中同时出现这两种形式会很不协调,JRuby很聪明地将Java中的fooBar转为了foo_bar,而常见的getter和setter,也简化为了成员属性的名称,foo是getFoo(),而foo=是setFoo()。
用to_java()能将一个Ruby的数组转换为Java中的Object[],如果想要指定数组的类型可以这样:

[1,2,3].to_java :float # new float[] {1,2,3}
["str", "str2"].to_java java.lang.String # new String[]{"str","str2"}

常用的symbol有以下几种::boolean、:byte、:char、:double、:float、:int、:long、:short、:object、:string、:big_decimal(:decimal)和:big_integer(:big_int)。

如要直接创建并使用Java数组,像下面这样就行了:

java.lang.String[3].new
java.lang.String[].new [3,3]
java.lang.String[3][3].new

d = java.lang.String[3,3].new
d[0][0] = "Hello"
d[0][1] = "World"

2.2. 扩展Java
对Java的扩展主要是用Ruby来实现接口和继承类。先来看下如何实现接口:

class Compare
  import java.lang.Comparable

  def compareTo o
    this <=> o
  end

end

如果要实现多个接口,import就可以了,对于未实现的方法,JRuby会把它交给method_missing。有一点要注意,compareTo在这里不能写成compare_to。
至于继承Java类就更容易了,几乎和继承Ruby类没什么区别:

class MyStringBuffer < java.lang.StringBuffer
  def append(v)
  end
end

StringBuffer类的append方法有多个overload的版本,接收多个不同类型的参数,它们都会被统一到这个唯一的方法上,理由嘛很好理解,不是吗?
除此之外,JRuby还为Java的集合类提供了很多扩展,让你能用Ruby的方式来操作Java集合。比方说,java.util.Map多了each方法、 []方法和[]=方法;java.lang.Comparable拥有了<=>方法;所有继承自java.util.Collection的类有了each、<<、+、-和length方法;java.util.List有了[]和[]=方法,还实现了sort和sort!方法。

2.3. Java中调用JRuby
Java 6中加入了JSR223,让Java可以支持脚本语言,如果你的运气没这么好,还停留在Java 5或者Java 1.4上,那可以考虑用BSF或者是直接用JRuby Runtime。当然,除非情况特殊,否则不推荐使用Runtime。
JSR223和BSF的用法比较相近,所以这里只演示一下JSR223。先去下载一个JSR223引擎包,把其中的JRuby引擎放进CLASSPATH。代码如下:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class JRubyJSR223 {
  public static void main(String[] args) throws Exception {
    ScriptEngineManager m = new ScriptEngineManager();
    ScriptEngine rubyEngine = m.getEngineByName("jruby");
    rubyEngine.getContext().setAttribute("num", new Integer(4), ScriptContext.ENGINE_SCOPE);
    rubyEngine.eval("puts 2 + $num ");
  }
}

3. JRuby on Rails项目的部署
既然是RoR的项目,自然是可以借鉴已有的最佳实践,JavaEye上对此已有很多讨论。不过目前还不能在JRuby on Rails中使用FastCGI,所以像JavaEye用的LightTPD+FastCGI就只能被暂时忽略了,等到FastCGI什么时候被JRuby on Rails支持了再让它重见天日吧。
既然用JRuby而非Ruby,那自然是有一定原因的,不是想在系统中使用Java资源,就是开发者有浓厚的Java情结。既然是JRuby on Rails,就让我们来看下Java开发者会比较喜欢的部署方式。

3.1. Java EE Web容器中的部署
如果RoR的项目跑在Tomcat里,那会是种什么感觉?如果Ruby文件全变成class了又会怎么样?这可不是睁眼说瞎话,在JRuby on Rails里你就能这么做!
GoldSpike能够把整个Rails应用程序打包为一个War文件,有了War就能在任意Java EE Web容器中进行直接的部署。
以插件形式安装好GoldSpike后,可以在Rails项目中用它提供的Rake任务来生成War文件。GoldSpike的配置都做在config/war.rb文件中,用如下命令开始构建,运行后会生成一个与项目同名的War文件:

jruby -S rake war:standalone:create

下面来介绍些war.rb配置时的DSL:

写道
exclude_files FILENAME 用来指定不想被放入War的文件,可以使用通配符。
servlet CLASSNAME 分派Rails请求的类,默认是org.jruby.webapp.RailsServlet。
compile_ruby BOOLEAN 打包前编译所有的Ruby文件,目前这个功能似乎还不是很理想,所以默认是false。记得Robbin以前曾发过一篇文章说突然发现XRuby做的事情很有前途,JRuby同样能够做到,其实我不在乎用什么,只要把我的Ruby代码编程字节码就行。
add_gem NAME, VERSION 你需要手动添加程序用到的Gem包,好在有add_gem_dependencies,把它设为true(默认就是true),GoldSpike会自动添加依赖的包的。

add_gem 'RedCloth', '= 3.0.4' 

datasource_jndi BOOLEAN 如果在程序中使用了JNDI提供数据源,那将这个参数设置为true,并用datasource_jndi_name NAME来提供JNDI名称,JRuby on Rails中可以用ActiveRecord-JDBC来访问数据库,其中能够使用JNDI。
maven_library GROUP, NAME, VERSION 项目中如果需要Jar库,GoldSpike可以直接从Maven库中下载文件。

maven_library 'mysql', 'mysql-connector-java', '5.0.4'  

GoldSpike是JRuby-extras的一部分,欲了解相关信息,请访问https://rubyforge.org/projects/jruby-extras/ ,其中还有ActiveRecord-JDBC等信息。此外,由Nick Sieger开发的Warbler也是一个不错的选择。

3.2. Mongrel集群
在RoR中常会启动一组Mongrel来处理请求,JRuby on Rails中同样可以这么做,只是在做法上有所不同,因为直接启动几个Mongrel实例的同时会起好几个JVM,启动速度慢不说,还很耗资源,所以JRuby提供了一种机制,在同一个JVM中启动几个JRuby Runtime来运行程序。我们可以利用这种机制在一个JVM中启动几个Mongrel监听连续端口。这里会用到mongrel_jcluster,建议在用Gem安装Mongrel时就一起把这个mongrel_jcluster装了,你总是会用到的。
配置、启动及停止的命令如下:

jruby -S mongrel_rails jcluster::configure -e production -p 4000 -c . -N 4 -R 20202 -K yourVerySecretKey
jruby -S mongrel_rails jcluster::start
jruby -S mongrel_rails jcluster::stop

第一条命令会创建一个配置文件,启动4个Mongrel实例,端口从4000开始,JRuby通过20202端口来监听发送的命令(JRuby自己起了个服务器,接收命令,在一个JVM里运行),-K是服务器用的密钥。
至于放在Mongrel前处理静态资源及负载均衡的服务器,请自行查阅网上其他资源。

4. 总结
本文简单地介绍了JRuby中Ruby与Java的互操作和JRuby on Rails项目的部署问题,希望能够起到一个抛砖引玉的作用,让大家更多地关注JRuby,虽然它还有这样那样的问题,但也不失为一个好的选择。
JRuby目前的最大目标是与Ruby兼容,所以大量的精力都放在处理兼容性上,相信以后在性能上会有所提高,其实JRuby的速度已经慢慢接近C Ruby了。再者,JRuby背后有Sun的支持,NetBeans IDE 6.0中默认带了JRuby支持,GlassFish V3也将对它有所支持,这不都暗示JRuby将有所作为吗?

分享到:
评论
25 楼 iMzw 2008-02-25  
大家可以看看这篇文章。
http://docs.google.com/Doc?id=dg679957_10fn3fhmcn

我当时Reseach JRuby call Java,准备使用JRuby On Rails。最终转向了Groovy on Grails。我的原因(仅仅是个人原因)
1.性能
2.Rails无法很好的Tomcat中运行。
3.RubyAMF 功能不是很强(我要用AMF,而BlazeDS很好(Java))
4.JRuby与Java互操作很繁琐,而且有很多兼容性问题。
24 楼 mathgl 2008-02-21  
只有适合与否的语言吧。语言的流行也要看一点点运气的
23 楼 pig345 2008-02-19  
robbin 写道
pig345 写道
诚恳地问一个重要的问题:使用C编写的第三方Ruby库能在JRuby里面使用么???

不能,但是如果你用JRuby的话,Java肯定会有相应版本的库。比方说ferret,你可以用Java的lucene,而且可能更好,比方说Rmagick,你可以用Java 2D等等。

不过也有一些C库,提供了jruby版本的gem,比方说hpricot。


谢了robbin,这样在Ruby和JRuby之间平滑移植,是不大可能了,比较麻烦。
22 楼 ningshuihan 2008-02-18  
不要重复你自己
惯例优于配置

光这两条原则就挺诱惑人的,呵呵
21 楼 ningshuihan 2008-02-18  
不错,rails学习中
20 楼 siuying 2008-02-07  
DigitalSonic 写道
Ruby的确是有些年头了,和Java差不多,但在Rails出现前普及度不高,甚至都没什么人知道。虽然Ruby可以做的东西很多(我用Ruby在Freebsd下做过流量监控限制的系统),但大多数人在讲到Ruby时都会把它和Rails联系起来,和Web开发联系起来,它在这方面的确不错,这是有目共睹的。

个人认为一般情况下语言本身并没有什么特别的好坏之分,拿JavaScript举个例子,在Web 2.0热起来前,多数人只是用JavaScript做点小特效,搞点表单验证,少有大的应用,但现在呢?它到底算好还是不好?有时真的只是机遇问题而已。

没有人说Ruby是银弹,Ruby和JRuby只是给你多一个选择而已,多条路又不是坏事,至于用或不用根据实际情况自己判断就好了。


語言有清楚的好壞之分。 試問如果 Java 跟 C 一樣,為甚麼今天的中間件都是用 Java 而不是用 C 呢?或者為甚麼人們用 C/C++ 寫 OS 不再用 FORTRAN呢?

一些在 Java 一定要攪 AOP 才有的特性,在 Ruby 可以輕易做到。Closure 很美妙,讓那些無用的 inner class 都不用了。還有因為動態語言的關系讓編程精簡許多,看一個標準的 Active Records 的類比同樣的 Hibernate 的類簡短優雅得多。。。 當然要是以現在的掙錢能力來說, Java 還是最好的,但我會同時放眼留意著最好的新平台。
19 楼 siuying 2008-02-07  
ken1984 写道
鸡肋,新瓶装旧酒,就像PHP也可以引用JAVA一样。


不同。JRuby on Rails 可以讓 Rails 的軟件直接 deploy 進 Java Container ,並使用 Java 的 Library。

是說服老闆轉用 Rails 的好方法... "這是在 Java Container 上運行的系統"
18 楼 庄表伟 2008-02-04  
xiaolin0105 写道
sonicluo3 写道
现在java的最主要的创新是JVM而非java语法本身,让各种编程语言跑在同一个平台(JVM)里面是一件非常美妙的事情.

你是说.net的clr? 我不知道jvm还可以跑java以外的编程语言啊?除非把其他语言都编译成java bytecode...


Programming Languages for the Java Virtual Machine
17 楼 xiaolin0105 2008-02-04  
sonicluo3 写道
现在java的最主要的创新是JVM而非java语法本身,让各种编程语言跑在同一个平台(JVM)里面是一件非常美妙的事情.

你是说.net的clr? 我不知道jvm还可以跑java以外的编程语言啊?除非把其他语言都编译成java bytecode...
16 楼 robbin 2008-01-30  
pig345 写道
诚恳地问一个重要的问题:使用C编写的第三方Ruby库能在JRuby里面使用么???

不能,但是如果你用JRuby的话,Java肯定会有相应版本的库。比方说ferret,你可以用Java的lucene,而且可能更好,比方说Rmagick,你可以用Java 2D等等。

不过也有一些C库,提供了jruby版本的gem,比方说hpricot。
15 楼 pig345 2008-01-30  
诚恳地问一个重要的问题:使用C编写的第三方Ruby库能在JRuby里面使用么???
14 楼 DigitalSonic 2008-01-29  
Ruby的确是有些年头了,和Java差不多,但在Rails出现前普及度不高,甚至都没什么人知道。虽然Ruby可以做的东西很多(我用Ruby在Freebsd下做过流量监控限制的系统),但大多数人在讲到Ruby时都会把它和Rails联系起来,和Web开发联系起来,它在这方面的确不错,这是有目共睹的。

个人认为一般情况下语言本身并没有什么特别的好坏之分,拿JavaScript举个例子,在Web 2.0热起来前,多数人只是用JavaScript做点小特效,搞点表单验证,少有大的应用,但现在呢?它到底算好还是不好?有时真的只是机遇问题而已。

没有人说Ruby是银弹,Ruby和JRuby只是给你多一个选择而已,多条路又不是坏事,至于用或不用根据实际情况自己判断就好了。
13 楼 spring5365 2008-01-29  
都说ruby怎么怎么好,但问个问题为什么ruby93年出来,java 95年出来的,但现在java成熟的技术和实现的项目要比ruby多很多呢?还是实践能证明一切吧
12 楼 庄表伟 2008-01-28  
aninfeel 写道
对这种炒作的东西已经心灰意冷了

人家好好的写一篇技术文章,怎么就成炒作了?
11 楼 aninfeel 2008-01-28  
对这种炒作的东西已经心灰意冷了
10 楼 DigitalSonic 2008-01-28  
ken1984 写道
鸡肋,新瓶装旧酒,就像PHP也可以引用JAVA一样。

也不能这么说,两者还是有区别的,JRuby并非为了在Ruby中引用Java才搞的。
引用
JRuby is a 100% Java implementation of the Ruby programming language. It is Ruby for the JVM.

JRuby provides a complete set of core "builtin" classes and syntax for the Ruby language, as well as most of the Ruby Standard Libraries. The standard libraries are mostly Ruby's own complement of .rb files, but a few that depend on C language-based extensions have been reimplemented. Some are still missing, but we hope to implement as many as is feasible.
9 楼 Godlikeme 2008-01-27  
兼容带来的后果就是一团糟,发展路线不会很清晰,Jmess.
还是早日有个了断吧。
8 楼 zzsczz 2008-01-27  
hibernate vs ejb,jdo

jruby vs groovy

本来没什么标准的,用的人多了就是事实标准

有的软件是根据需要进化而来,而有的是认为捏造的。。
7 楼 ken1984 2008-01-26  
鸡肋,新瓶装旧酒,就像PHP也可以引用JAVA一样。
6 楼 liuzongan 2008-01-26  
好,谢谢您,写得不错啊

相关推荐

    深度剖析Ruby vs Java误区

    在深入探讨Ruby与Java之间的误区时,我们首先要澄清一个普遍的误解:Ruby只适合小型项目,而Java更适合大型复杂项目。事实上,根据James Halloway的观点,选择哪种语言取决于项目的特点和需求。对于小型项目,Ruby ...

    From Java to Ruby

    它引导读者了解从传统的Java编程环境过渡到Ruby的动态世界时所遇到的概念差异和技术挑战。Ruby是一种灵活、简洁且富有表现力的编程语言,它提倡元编程和代码简洁性,与Java的面向对象特性有所不同。 首先,我们要...

    跨越边界:闭包

    然而,对于某些社区,如Java,闭包的引入引发了一些争议。一些开发者认为闭包增加了语言的复杂性,破坏了简洁性,而另一些人则相信它们能带来新的设计模式和效率提升。 闭包的核心在于它可以捕获和存储其定义时的...

    ruby生成java文件的工具

    标题中的“ruby生成java文件的工具”指的是使用Ruby编程语言编写的一种工具,它能够自动生成Java源代码。这种工具通常用于提高开发效率,特别是在需要大量重复性代码的情况下,如数据访问对象(DAO)、控制器...

    基于Ruby+Java搜索引擎原理与实现

    《基于Ruby+Java搜索引擎原理与实现》是一部深入探讨搜索引擎技术的书籍,虽然只涵盖了前三个章节,但已足以让我们对搜索引擎的基本运作有初步的理解。在本文中,我们将围绕Ruby和Java这两种编程语言如何应用于搜索...

    跨越边界:REST on Rails

    Ruby on Rails是一个突然流行起来的框架,充当着Ruby编程语言的催化剂。随着Ruby的经验不断成功,开发人员开始寻求把他们的...本文介绍了如何在Ruby on Rails中添加REST风格的Web服务,并从Ruby和Java代码调用服务。

    对Ruby VS Java误区的深度剖析

    Stuart Halloway的"Ruby VS Java 之怪谈"系列博客深入探讨了关于这两种语言的一些常见误解,旨在为开发者提供更全面的理解。以下是对这些误区的详细分析: 误区一:Ruby适合小型项目,Java适合大型复杂项目。...

    从 Java 到 Ruby_ 每一个管理者应该知道的事情

    标题 "从 Java 到 Ruby_ 每一个管理者应该知道的事情" 提示我们,这篇文章或书籍将探讨在 IT 管理领域从使用 Java 转向 Ruby 的关键点。Ruby 是一种动态类型、面向对象的编程语言,以其简洁、灵活的语法和强大的元...

    Java世界的Ruby

    ### Java世界的Ruby:动态脚本的新篇章 #### 引言 在软件开发的历史长河中,从最初的机器语言到后来的高级语言,每一次技术的进步都伴随着开发者对于新工具的探索与旧工具的不舍。Java作为一种重要的面向对象编程...

    ruby2java:查尔斯·纳特(Charles Nutter)的JRuby项目的分支,该项目从Ruby源代码构建Java .class文件-java project source code

    Ruby2Java是Charles Nutter发起的一个项目,它是JRuby的分支,主要目标是将Ruby语言的源代码直接编译成Java字节码(.class文件)。这个项目旨在提高Ruby在Java平台上的性能,并且利用Java虚拟机(JVM)的优势,使得...

    ruby_vs_java_recursion:Ruby 与 Java

    ruby_vs_java_recursion Ruby vs Java:为什么世界会用 Java 更快地结束? 该 repo 显示了 Hanoi Towers 上的经典递归调用。 上有Java、JRuby、Ruby实现的比较结果

    Java与Ruby在Web开发上谁更高效

    【Java与Ruby在Web开发上的效率对比】 Java和Ruby都是流行的Web开发语言,它们各自有其独特的优点和适用场景。本文主要探讨了Java相对于Ruby在Web开发中的效率和生产力。 首先,Ruby on Rails(RoR)以其简洁、...

    From java to Ruby

    ### 从 Java 到 Ruby:理解两种编程语言的转变 #### 概述 《从 Java 到 Ruby》这本书由 Bruce Tate 所著,旨在帮助 Java 开发者了解并过渡到 Ruby 这一更为灵活和高效的编程语言。本书不仅对 Ruby 的核心概念和...

    跨越边界 Ajax on Rails

    **Ajax on Rails:跨越边界的Web交互技术** Ajax(Asynchronous JavaScript and XML)技术的引入,为Web应用程序带来了革命性的变化,它使得页面无需刷新就能实现数据的动态更新,极大地提升了用户体验。Rails作为...

    Ruby-JRuby一个Ruby语言的Java实现

    通过在JVM上运行,JRuby可以无缝地与Java代码交互,使得开发人员能够利用Ruby的生产力优势以及Java的稳定性和企业级服务。 JRuby的实现方式是将Ruby源代码转换为Java字节码,然后在JVM上执行。这种转换过程涉及到...

    跨越边界1:Ajax on Rails

    【标题】:“跨越边界1:Ajax on Rails” 【描述】:本文主要探讨了Ajax技术如何与Ruby on Rails框架相结合,创造出高度交互性的Web应用。Ajax技术利用XML、JavaScript和Web标准,通过异步通信增强用户体验,而Ruby...

    巧妙规避Java与Ruby语言迁移过程中的风险

    本文主要探讨了Java和Ruby这两种语言在迁移过程中可能遇到的问题,以及如何巧妙地规避这些风险。 首先,Java作为一种成熟的编程语言,自1996年推出以来已经在服务端编程中占据了主导地位。它的优势在于高效、稳定,...

Global site tag (gtag.js) - Google Analytics