`
missall
  • 浏览: 127659 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Jruby和ruby互操作[转]

阅读更多
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  

require 'java'


java::java.util.ArrayListJava类的使用也有几种选择:


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"  

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" 

JString = java.lang.String
y = JString.new "Hello, world"你可以这样来调用System.out.println:


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

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"}  

[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"  

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  

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  

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

endStringBuffer类的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 ");   
  }   
}  

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  

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'   

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' 
  

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  

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将有所作为吗?
分享到:
评论

相关推荐

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

    同样,Java开发者也可以轻松地调用Ruby代码,实现语言间的互操作性。 JRuby的版本"jruby-jruby-7bee00d"可能是一个特定的Git提交版本,这表明它是一个开发版本,可能包含了最新的功能和改进。通常,这样的版本会...

    jruby-core-1.7.12.zip

    4. JRuby 还可以作为 Java 代码调用 Ruby 代码的桥梁,通过 JRuby API 实现 Java 和 Ruby 之间的互操作。 关于 sbuild-https-plugin: 1. sbuild-https-plugin 是 Debian 开发者用来增强 sbuild 功能的工具,允许...

    走近JRuby

    而“工具”标签则可能意味着博主会介绍一些使用JRuby的实用工具或框架,例如与Java库的互操作性、持续集成工具(如Jenkins)、测试框架(如JUnit或RSpec),以及如何在Java项目中集成JRuby脚本以提高开发效率。...

    JRuby在Java测试中的应用

    二是通过其与Java之间的互操作性来增强测试的能力。Ruby语言的灵活性让开发者能够快速地构建出复杂的测试场景,而JRuby又使得这些脚本可以直接在Java环境中运行,无需额外的配置或编译步骤。 #### 为什么选择Ruby?...

    ruby-2.6.9.tar.gz

    同时,对于JRuby来说,可能有对JVM优化的更新,使得Ruby代码在Java平台上运行得更快,以及与Java库更好的互操作性。 总的来说,Ruby-2.6.9.tar.gz是一个为开发者准备的软件包,包含了在不同平台上编译和使用Ruby ...

    j-monkeybars.zip(使用 JRuby 和 Swing 进行跨平台开发的源代码)

    通过分析这些源代码,开发者可以学习到如何在JRUBY中调用Java类,理解JRuby与Java之间的互操作性,例如使用`Java::JavaLang::System`来访问Java的系统类,或者使用`JRuby::JavaExtensions`来增强Ruby对象的Java功能...

    jruby-bin-1.5.5.zip java脚本编程

    3. **互操作性**:JRuby允许Ruby代码直接调用Java类库,反之亦然。这意味着你可以轻松地利用Java平台的强大功能,如数据库连接、多线程和网络编程,同时享受Ruby的简洁语法和动态特性。 4. **热部署**:由于JRuby是...

    android ruby解释器

    JRuby不仅实现了Ruby标准库,还提供了与Java平台的互操作性,使得Android的API可以直接在Ruby代码中调用。 在Android平台上使用Ruby的主要优点包括: 1. **快速开发**:Ruby的简洁语法和强大的库(如Rails框架)...

    Java版的Ruby解释器 JRuby简介

    这展示了JRuby的互操作性,使得开发者可以轻松地在Ruby代码中使用Java组件。 在示例中,首先通过`require "java"`导入Java支持,然后使用`include_class`引入所需的Java类。接着,创建了一个TreeSet,并添加了一些...

    PDF-JRubyCookbookFreePdfBook-英文版.rar

    读者会学习到JRuby与Java的互操作性,这包括调用Java类库,以及将Java对象转换为Ruby对象和反之亦然。 书中的章节可能涵盖以下关键知识点: 1. **JRuby核心特性**:深入探讨JRuby的语法、面向对象编程、块、闭包和...

    clojruby:通过 JRuby 从 Clojure 调用 Ruby

    互操作Clojure 库旨在......好吧,那部分取决于您。用法要运行一个简单的示例,从 Ruby 调用 Java 类: jruby simple.rb要运行稍微复杂一点的示例,请从 Clojure 调用相同的 Java 类: lein run -m interop.simple要...

    聊聊Java平台上的非Java语言共3页.pdf.zip

    Ceylon的类型系统和模块化特性使其在大型项目中表现出色,而且它支持互操作性,可以与Java代码一起使用。 每种JVM语言都有其独特的优点和适用场景,开发者可以根据项目需求和团队喜好选择合适的语言。例如,Kotlin...

    jrubyconf-2015:JRubyConf.EU 2015谈话材料

    2. 代码示例:展示如何在JRuby中编写和运行Ruby代码,可能包括与Java互操作的实例。 3. 工作坊材料:提供动手实践的教程,帮助开发者熟悉JRuby环境,理解如何利用JVM的性能优势。 4. PPT幻灯片:会议演讲者的演示...

    jdk6.0从入门到精通-----chapter18与动态语言结合

    总的来说,这个主题涵盖了Java平台与动态语言的互操作性,对于希望提升开发效率和探索不同编程范式的Java开发者来说,是非常有价值的学习内容。通过学习这部分知识,开发者能够更好地利用Java生态系统的丰富资源,...

    EvolvingTheJavaPlatform-OlaBini.pdf

    Groovy 是一种动态、强类型的语言,具有面向对象的特点、灵活的 Java 互操作性、灵感来自 Python、Ruby 和 Smalltalk 等语言。Scala 是一种多范式语言,具有面向对象的特点、函数式编程的自然性、灵活的 Java 互操作...

    Darkart:二进制接口让Chez Scheme使用Python,Lua,Ruby等的库

    在计算机编程的世界中,语言间的互操作性是至关重要的。Chez Scheme,一种基于R5RS标准的Scheme实现,以其简洁、高效的特性深受程序员喜爱。然而,有时我们需要利用其他编程语言如Python、Lua或Ruby丰富的库资源。...

    jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.rar

    1. **改进的动态语言支持**:JDK 6增加了对动态语言的原生支持,如JavaScript和Ruby,通过JavaFX Script和JRuby等技术,增强了Java与这些语言的互操作性。 2. **增强的Swing组件**:JDK 6提升了Swing UI库的性能和...

    PHP的十个不容忽视的问题

    #### 三、PHP与其他语言的互操作性 ##### 3.1 跨语言调用 - **多语言支持**:PHP支持与多种语言进行交互,如Java、C#、Python、Perl、Lua和JavaScript等。 - **Ruby支持**:尽管目前没有直接支持Ruby的PHP扩展,但...

    javaeye月刊2008年5月 总第3期.pdf

    讨论可能涉及它们的优势、互操作性以及在图形用户界面设计中的未来角色。 4. **MyEclipse 6.5M1值得关注的特性**: - MyEclipse是基于Eclipse的集成开发环境(IDE),6.5M1版本的新特性可能包括性能提升、新功能...

Global site tag (gtag.js) - Google Analytics