小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Jruby和ruby互操作[轉(zhuǎn)]

 gischen 2009-01-04

Jruby和ruby互操作[轉(zhuǎn)]

1. 引言
2004年Ruby on Rails的橫空出世讓大家為之一驚,很多Java社區(qū)對(duì)它也投去關(guān)注的目光,現(xiàn)在RoR已經(jīng)漸漸為人接受,被運(yùn)用于不少實(shí)際項(xiàng)目之中,這也讓本來(lái)不怎么吸引眼球的Ruby從角落里走了出來(lái)。不少開(kāi)發(fā)者在試用了Ruby和RoR后產(chǎn)生了濃厚的興趣,畢竟Ruby的語(yǔ)法是如此的有趣,Rails中的開(kāi)發(fā)是如此的便捷,有時(shí)它替你安排好了一切,敲鍵盤就是了。
但Ruby畢竟和主流的Java/.Net還存在一定距離,比如開(kāi)發(fā)者數(shù)量,受關(guān)注度等等。更關(guān)鍵的是它缺乏像Java那樣的庫(kù)支持,很多時(shí)候不得不自己動(dòng)手“豐衣足食”。后來(lái)人們想到了要去跨越語(yǔ)言的邊界,但做總是比想要難,好在出現(xiàn)了JRuby,在它的幫助下,這條邊界已經(jīng)不再不可逾越,所以勇敢地跨出第一步吧!

2. JRuby的Java集成
如何讓Ruby與Java緊密地結(jié)合在一起呢?你可以在Ruby中引用Java類、Java原子類型、Java數(shù)組,實(shí)現(xiàn)Java接口,繼承Java類;也可以在Java中使用Ruby的代碼。其實(shí)一切都很簡(jiǎn)單,你需要的只是一點(diǎn)小小的魔法而已。

2.1. JRuby中調(diào)用Java
在接觸JRuby前我使用過(guò)RJB(Ruby Java Bridge,http://rjb./),兩者都提供在Ruby中調(diào)用Java的功能,僅在這點(diǎn)上來(lái)說(shuō),感覺(jué)它們差不多,其實(shí)JRuby的功能要強(qiáng)大的多。如果你只是想在Ruby中簡(jiǎn)單地調(diào)用一些Java代碼,那可以考慮RJB。
要在JRuby中使用Java,先要聲明程序中需要Java集成,有兩種方法,一種用require 'java';另一種直接使用java::java.util.ArrayList這樣的語(yǔ)法。無(wú)論是何種方法,都要保證所用的Java類在CLASSPATH中。


Ruby代碼 復(fù)制代碼
  1. require 'java'     
  2.      
  3. java::java.util.ArrayList     
  4.   
  5. require 'java'  


java::java.util.ArrayListJava類的使用也有幾種選擇:


Ruby代碼 復(fù)制代碼
  1. include_class "java.util.HashMap"     
  2. x = HashMap.new     
  3. x.put("foo","bar")      
  4.      
  5. include_class("java.lang.String") {|pkg,name| "JString"}      
  6. y = JString.new "Hello, world"     
  7.   
  8. include_class "java.util.HashMap"  
  9. x = HashMap.new  
  10. x.put("foo","bar")   
  11.   
  12. 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"你可以這樣來(lái)調(diào)用System.out.println:


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

java.lang.System.out.println("Hello, world")值得一提的是這里的”Hello, world”是Ruby的字符串,而非java.lang.String,JRuby會(huì)自動(dòng)對(duì)一些類型進(jìn)行轉(zhuǎn)換,開(kāi)發(fā)者無(wú)需自己動(dòng)手。
在Java中,方法和變量都用fooBar這樣的形式,而Ruby中則是foo_bar,顯然在代碼中同時(shí)出現(xiàn)這兩種形式會(huì)很不協(xié)調(diào),JRuby很聰明地將Java中的fooBar轉(zhuǎn)為了foo_bar,而常見(jiàn)的getter和setter,也簡(jiǎn)化為了成員屬性的名稱,foo是getFoo(),而foo=是setFoo()。
用to_java()能將一個(gè)Ruby的數(shù)組轉(zhuǎn)換為Java中的Object[],如果想要指定數(shù)組的類型可以這樣:


Ruby代碼 復(fù)制代碼
  1. [1,2,3].to_java :float # new float[] {1,2,3}      
  2. ["str""str2"].to_java java.lang.String # new String[]{"str","str2"}     
  3.   
  4. [1,2,3].to_java :float # new float[] {1,2,3}   
  5. ["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)。

如要直接創(chuàng)建并使用Java數(shù)組,像下面這樣就行了:

Ruby代碼 復(fù)制代碼
  1. java.lang.String[3].new     
  2. java.lang.String[].new [3,3]      
  3. java.lang.String[3][3].new     
  4.      
  5. d = java.lang.String[3,3].new     
  6. d[0][0] = "Hello"     
  7. d[0][1] = "World"     
  8.   
  9. java.lang.String[3].new  
  10. java.lang.String[].new [3,3]   
  11. java.lang.String[3][3].new  
  12.   
  13. d = java.lang.String[3,3].new  
  14. d[0][0] = "Hello"  

d[0][1] = "World"2.2. 擴(kuò)展Java
對(duì)Java的擴(kuò)展主要是用Ruby來(lái)實(shí)現(xiàn)接口和繼承類。先來(lái)看下如何實(shí)現(xiàn)接口:


Ruby代碼 復(fù)制代碼
  1. class Compare      
  2.   import java.lang.Comparable      
  3.      
  4.   def compareTo o      
  5.     this <=> o      
  6.   end     
  7.      
  8. end     
  9.   
  10. class Compare   
  11.   import java.lang.Comparable   
  12.   
  13.   def compareTo o   
  14.     this <=> o   
  15.   end  


end如果要實(shí)現(xiàn)多個(gè)接口,import就可以了,對(duì)于未實(shí)現(xiàn)的方法,JRuby會(huì)把它交給method_missing。有一點(diǎn)要注意,compareTo在這里不能寫成compare_to。
至于繼承Java類就更容易了,幾乎和繼承Ruby類沒(méi)什么區(qū)別:


Ruby代碼 復(fù)制代碼
  1. class MyStringBuffer < java.lang.StringBuffer      
  2.   def append(v)      
  3.   end     
  4. end     
  5.   
  6. class MyStringBuffer < java.lang.StringBuffer   
  7.   def append(v)   
  8.   end  

endStringBuffer類的append方法有多個(gè)overload的版本,接收多個(gè)不同類型的參數(shù),它們都會(huì)被統(tǒng)一到這個(gè)唯一的方法上,理由嘛很好理解,不是嗎?
除此之外,JRuby還為Java的集合類提供了很多擴(kuò)展,讓你能用Ruby的方式來(lái)操作Java集合。比方說(shuō),java.util.Map多了each方法、 []方法和[]=方法;java.lang.Comparable擁有了<=>方法;所有繼承自java.util.Collection的類有了each、<<、+、-和length方法;java.util.List有了[]和[]=方法,還實(shí)現(xiàn)了sort和sort!方法。

2.3. Java中調(diào)用JRuby
Java 6中加入了JSR223,讓Java可以支持腳本語(yǔ)言,如果你的運(yùn)氣沒(méi)這么好,還停留在Java 5或者Java 1.4上,那可以考慮用BSF或者是直接用JRuby Runtime。當(dāng)然,除非情況特殊,否則不推薦使用Runtime。
JSR223和BSF的用法比較相近,所以這里只演示一下JSR223。先去下載一個(gè)JSR223引擎包,把其中的JRuby引擎放進(jìn)CLASSPATH。代碼如下:


Java代碼 復(fù)制代碼
  1. import javax.script.ScriptEngine;      
  2. import javax.script.ScriptEngineManager;      
  3.      
  4. public class JRubyJSR223 {      
  5.   public static void main(String[] args) throws Exception {      
  6.     ScriptEngineManager m = new ScriptEngineManager();      
  7.     ScriptEngine rubyEngine = m.getEngineByName("jruby");      
  8.     rubyEngine.getContext().setAttribute("num"new Integer(4), ScriptContext.ENGINE_SCOPE);      
  9.     rubyEngine.eval("puts 2 + $num ");      
  10.   }      
  11. }     
  12.   
  13. import javax.script.ScriptEngine;   
  14. import javax.script.ScriptEngineManager;   
  15.   
  16. public class JRubyJSR223 {   
  17.   public static void main(String[] args) throws Exception {   
  18.     ScriptEngineManager m = new ScriptEngineManager();   
  19.     ScriptEngine rubyEngine = m.getEngineByName("jruby");   
  20.     rubyEngine.getContext().setAttribute("num"new Integer(4), ScriptContext.ENGINE_SCOPE);   
  21.     rubyEngine.eval("puts 2 + $num ");   
  22.   }  

}3. JRuby on Rails項(xiàng)目的部署
既然是RoR的項(xiàng)目,自然是可以借鑒已有的最佳實(shí)踐,JavaEye上對(duì)此已有很多討論。不過(guò)目前還不能在JRuby on Rails中使用FastCGI,所以像JavaEye用的LightTPD+FastCGI就只能被暫時(shí)忽略了,等到FastCGI什么時(shí)候被JRuby on Rails支持了再讓它重見(jiàn)天日吧。
既然用JRuby而非Ruby,那自然是有一定原因的,不是想在系統(tǒng)中使用Java資源,就是開(kāi)發(fā)者有濃厚的Java情結(jié)。既然是JRuby on Rails,就讓我們來(lái)看下Java開(kāi)發(fā)者會(huì)比較喜歡的部署方式。

3.1. Java EE Web容器中的部署
如果RoR的項(xiàng)目跑在Tomcat里,那會(huì)是種什么感覺(jué)?如果Ruby文件全變成class了又會(huì)怎么樣?這可不是睜眼說(shuō)瞎話,在JRuby on Rails里你就能這么做!
GoldSpike能夠把整個(gè)Rails應(yīng)用程序打包為一個(gè)War文件,有了War就能在任意Java EE Web容器中進(jìn)行直接的部署。
以插件形式安裝好GoldSpike后,可以在Rails項(xiàng)目中用它提供的Rake任務(wù)來(lái)生成War文件。GoldSpike的配置都做在config/war.rb文件中,用如下命令開(kāi)始構(gòu)建,運(yùn)行后會(huì)生成一個(gè)與項(xiàng)目同名的War文件:

Ruby代碼 復(fù)制代碼
  1. jruby -S rake war:standalone:create    

jruby -S rake war:standalone:create下面來(lái)介紹些war.rb配置時(shí)的DSL:

寫道
exclude_files FILENAME 用來(lái)指定不想被放入War的文件,可以使用通配符。
servlet CLASSNAME 分派Rails請(qǐng)求的類,默認(rèn)是org.jruby.webapp.RailsServlet。
compile_ruby BOOLEAN 打包前編譯所有的Ruby文件,目前這個(gè)功能似乎還不是很理想,所以默認(rèn)是false。記得Robbin以前曾發(fā)過(guò)一篇文章說(shuō)突然發(fā)現(xiàn)XRuby做的事情很有前途,JRuby同樣能夠做到,其實(shí)我不在乎用什么,只要把我的Ruby代碼編程字節(jié)碼就行。
add_gem NAME, VERSION 你需要手動(dòng)添加程序用到的Gem包,好在有add_gem_dependencies,把它設(shè)為true(默認(rèn)就是true),GoldSpike會(huì)自動(dòng)添加依賴的包的。


Ruby代碼 復(fù)制代碼
  1. add_gem 'RedCloth''= 3.0.4'      
  2.   
  3. add_gem 'RedCloth''= 3.0.4'   

datasource_jndi BOOLEAN 如果在程序中使用了JNDI提供數(shù)據(jù)源,那將這個(gè)參數(shù)設(shè)置為true,并用datasource_jndi_name NAME來(lái)提供JNDI名稱,JRuby on Rails中可以用ActiveRecord-JDBC來(lái)訪問(wèn)數(shù)據(jù)庫(kù),其中能夠使用JNDI。
maven_library GROUP, NAME, VERSION 項(xiàng)目中如果需要Jar庫(kù),GoldSpike可以直接從Maven庫(kù)中下載文件。


Ruby代碼 復(fù)制代碼
  1. maven_library 'mysql''mysql-connector-java''5.0.4'   
  

maven_library 'mysql', 'mysql-connector-java', '5.0.4'  GoldSpike是JRuby-extras的一部分,欲了解相關(guān)信息,請(qǐng)?jiān)L問(wèn)https:///projects/jruby-extras/ ,其中還有ActiveRecord-JDBC等信息。此外,由Nick Sieger開(kāi)發(fā)的Warbler也是一個(gè)不錯(cuò)的選擇。

3.2. Mongrel集群
在RoR中常會(huì)啟動(dòng)一組Mongrel來(lái)處理請(qǐng)求,JRuby on Rails中同樣可以這么做,只是在做法上有所不同,因?yàn)橹苯訂?dòng)幾個(gè)Mongrel實(shí)例的同時(shí)會(huì)起好幾個(gè)JVM,啟動(dòng)速度慢不說(shuō),還很耗資源,所以JRuby提供了一種機(jī)制,在同一個(gè)JVM中啟動(dòng)幾個(gè)JRuby Runtime來(lái)運(yùn)行程序。我們可以利用這種機(jī)制在一個(gè)JVM中啟動(dòng)幾個(gè)Mongrel監(jiān)聽(tīng)連續(xù)端口。這里會(huì)用到mongrel_jcluster,建議在用Gem安裝Mongrel時(shí)就一起把這個(gè)mongrel_jcluster裝了,你總是會(huì)用到的。
配置、啟動(dòng)及停止的命令如下:

Ruby代碼 復(fù)制代碼
  1. jruby -S mongrel_rails jcluster::configure -e production -p 4000 -c . -N 4 -R 20202 -K yourVerySecretKey      
  2. jruby -S mongrel_rails jcluster::start     
  3. jruby -S mongrel_rails jcluster::stop     
  4.   
  5. jruby -S mongrel_rails jcluster::configure -e production -p 4000 -c . -N 4 -R 20202 -K yourVerySecretKey   
  6. jruby -S mongrel_rails jcluster::start  

jruby -S mongrel_rails jcluster::stop第一條命令會(huì)創(chuàng)建一個(gè)配置文件,啟動(dòng)4個(gè)Mongrel實(shí)例,端口從4000開(kāi)始,JRuby通過(guò)20202端口來(lái)監(jiān)聽(tīng)發(fā)送的命令(JRuby自己起了個(gè)服務(wù)器,接收命令,在一個(gè)JVM里運(yùn)行),-K是服務(wù)器用的密鑰。
至于放在Mongrel前處理靜態(tài)資源及負(fù)載均衡的服務(wù)器,請(qǐng)自行查閱網(wǎng)上其他資源。

4. 總結(jié)
本文簡(jiǎn)單地介紹了JRuby中Ruby與Java的互操作和JRuby on Rails項(xiàng)目的部署問(wèn)題,希望能夠起到一個(gè)拋磚引玉的作用,讓大家更多地關(guān)注JRuby,雖然它還有這樣那樣的問(wèn)題,但也不失為一個(gè)好的選擇。
JRuby目前的最大目標(biāo)是與Ruby兼容,所以大量的精力都放在處理兼容性上,相信以后在性能上會(huì)有所提高,其實(shí)JRuby的速度已經(jīng)慢慢接近C Ruby了。再者,JRuby背后有Sun的支持,NetBeans IDE 6.0中默認(rèn)帶了JRuby支持,GlassFish V3也將對(duì)它有所支持,這不都暗示JRuby將有所作為嗎?

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多