目前,Ruby on Rails正在成為Web應(yīng)用程序開發(fā)的新途徑。Ruby on Rails是基于Ruby語言的輕型Web開發(fā)架構(gòu),不僅開發(fā)效率高(部署容易)、功能豐富(支持Ajax等最新應(yīng)用),而且性能方面表現(xiàn)相當(dāng)出色。該架構(gòu)的支持者們聲稱Ruby on Rails開發(fā)人員的生產(chǎn)率最多是使用傳統(tǒng)J2EE架構(gòu)的10倍。也有測試資料顯示,該架構(gòu)性能比輕量級J2EE架構(gòu)Struts+Hibernate還高15%-30%。
二、兩種架構(gòu)的關(guān)鍵特性
2.1 Ruby on Rails 架構(gòu)
Ruby是一種解釋型面向?qū)ο竽_本語言,由日本的Yukihiro Matsumoto在1993年2月24日首次發(fā)布。Ruby從Perl,Eiffel等語言中吸收了很多特性,使之很適合用于文本文件處理和進(jìn)行系統(tǒng)管理任務(wù),并且完全面向?qū)ο?。它的語法簡單明快,可擴(kuò)展并且可以跨平臺。Ruby是完全自由開放的,不僅可以免費(fèi)得到,而且可以自由地使用、復(fù)制、修改和分發(fā)它。
Ruby on Rails是用Ruby編寫的一款完整的、開放源代碼Web架構(gòu),目的是使用更簡單而且更少的代碼開發(fā)實際使用的應(yīng)用程序。作為一個完整的框架,Ruby on Rails中的所有的層都是為協(xié)同工作而構(gòu)造的,可以完全只使用一門單一的語言。在Rails中,所有內(nèi)容(從模板到控制流再到業(yè)務(wù)邏輯)都是用Ruby編寫的。Rails支持基于配置文件和注釋的反射(reflection)和運(yùn)行時擴(kuò)展。
Ruby on Rails是一種MVC架構(gòu),雖然該技術(shù)不是Rails所特有的——甚至不是Web應(yīng)用程序所特有的(相對于其他程序),但是Rails具有非常清晰而專一的MVC思維方式。
⑴模型
Rails應(yīng)用程序的模型部分主要是其所使用的底層數(shù)據(jù)庫,很多情形下是以一種受管理的方式對關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS)中的數(shù)據(jù)執(zhí)行操作的。
ActiveRecord類是Rails的一個核心組成部分,它將關(guān)系型表映射為Ruby對象,使其成為控制器可以操作并能在視圖中顯示的數(shù)據(jù)。Rails應(yīng)用程序可以支持ORACLE、DB2、MySQL等關(guān)系數(shù)據(jù)庫。
⑵控制器
控制器以其抽象形式執(zhí)行應(yīng)用程序的邏輯。Rails應(yīng)用程序的app/controllers/目錄中的Ruby腳本能把模型數(shù)據(jù)導(dǎo)入為變量,保存回去或?qū)ζ溥M(jìn)行修改和處理。不過,控制器不關(guān)心用戶如何適當(dāng)?shù)仫@示或者輸入數(shù)據(jù)。Rails僅局限于在Web頁中提供和收集數(shù)據(jù),但開發(fā)人員可以修改Web頁的布局——顏色、字體、表格、樣式表單等等,與控制器代碼無關(guān)。
⑶視圖
Rails視圖是用于編寫Ruby代碼的界面,包含有用于.rhtml的非常好的模板語言,它將純粹的HTML與嵌入的Ruby代碼組合起來。Rails應(yīng)用程序界面的最表層外觀通常是由CSS樣式表單控制的。.rhtml格式是一種增強(qiáng)的HTML,一個簡單的HTML文件本身也是一個合法的RHTML模板,但要考慮RHTML提供的腳本控制。
此外,Rails提供了一組代碼生成器工具,以替代使用嚴(yán)格的工作空間和IDE的開發(fā)環(huán)境。簡單的應(yīng)用程序可能完全不需要編碼,讓Rails在運(yùn)行時動態(tài)地生成客戶機(jī)HTML頁面。第一遍生成代碼時創(chuàng)建的只是粗略的支架,然后可以生成更詳細(xì)的能夠定制的控制器、視圖和模型。
2.2 輕量級J2EE架構(gòu)Struts+Hibernate
2.2.1 Struts簡介
Struts是MVC設(shè)計模式的一種實現(xiàn),它將Servlet和JSP標(biāo)記(屬于J2EE規(guī)范)用作實現(xiàn)的一部分。Struts繼承了MVC的各項特性,并根據(jù)J2EE的特點(diǎn),做了相應(yīng)的變化與擴(kuò)展。Struts的體系結(jié)構(gòu)如圖1所示:

????????????????????????????????????????????????? 圖1 Struts體系結(jié)構(gòu)
Struts是Apache組織中開源項目之一,主要用于實現(xiàn)Web項目中表示層。Struts的核心是ActionSevlet,ActionServlet是一個通用的控制組件,承擔(dān)MVC中Controller的角色,其核心是Struts-config.xml。在Struts中,用戶的請求一般以*.do作為請求服務(wù)名,所有的*.do請求均被指向ActionSevlet,ActionSevlet根據(jù)Struts-config.xml中的配置信息,將用戶請求封裝成一個指定名稱的FormBean,并將此FormBean傳至指定名稱的ActionBean,由ActionBean完成相應(yīng)的業(yè)務(wù)操作,如文件操作,數(shù)據(jù)庫操作等。每一個*.do均有對應(yīng)的FormBean名稱和ActionBean名稱,這些在Struts-config.xml中配置。
2.2.2 Hibernate簡介
Hibernate是一種新的ORM映射工具,它不僅提供了從Java類到數(shù)據(jù)表之間的映射,也提供了數(shù)據(jù)查詢和恢復(fù)機(jī)制。相對于使用JDBC和SQL來手工操作數(shù)據(jù)庫,使用Hibernate,可以大大減少操作數(shù)據(jù)庫的工作量。
Hibernate可以和多種Web服務(wù)器或者應(yīng)用服務(wù)器良好集成,如今已經(jīng)支持幾乎所有的流行的數(shù)據(jù)庫服務(wù)器(達(dá)16種)。圖2顯示了Hibernate如何使用數(shù)據(jù)庫和配置文件數(shù)據(jù)庫來為應(yīng)用程序提供持久服務(wù)和持久化對象。
Hibernate的接口大致可以分為以下幾種類型:
●一些被用戶的應(yīng)用程序調(diào)用的,用來完成基本的創(chuàng)建、讀取、更新、刪除操作以及查詢操作的接口。這些接口是Hibernate實現(xiàn)用戶程序的商業(yè)邏輯的主要接口,它們包括Session、Transaction和Query。
●Hibernate用來讀取諸如映射表這類配置文件的接口,典型的代表有Configuration類。
●回調(diào)(Callback)接口。它允許應(yīng)用程序能對一些事件的發(fā)生作出相應(yīng)的操作,例如Interceptor、Lifecycle和Validatable都是這一類接口。
●一些可以用來擴(kuò)展Hibernate的映射機(jī)制的接口,例如UserType、CompositeUserType和IdentifierGenerator。這些接口可由用戶程序來實現(xiàn)(如果有必要)。

??????????????????????????????????????????? 圖2 Hibernate體系結(jié)構(gòu)
Hibernate使用了J2EE架構(gòu)中JDBC、JTA、JNDI等技術(shù)。其中JDBC是一個支持關(guān)系數(shù)據(jù)庫操作的一個基礎(chǔ)層;它與JNDI和JTA一起結(jié)合,使得Hibernate可以方便地集成到J2EE應(yīng)用服務(wù)器中去。
三、Ruby on Rails與Struts+Hibernate之比較分析
Ruby on Rails堆棧與輕量級J2EE 架構(gòu)Struts+Hibernate堆棧之間的基本區(qū)別很小,兩者都有用來執(zhí)行應(yīng)用程序代碼的容器,都有幫助分離應(yīng)用程序的模型、視圖和控件的MVC框架,以及持久存儲數(shù)據(jù)的機(jī)制。圖3是對兩種架構(gòu)堆棧的比較。
3.1前端控制器
Ruby on Rails的DispatchServlet和Struts的ActionServlet都是前端控制器模式的例子,它們提供了相同的功能。它們接受HTTP請求并解析URL,把請求的處理轉(zhuǎn)發(fā)給適當(dāng)?shù)膭幼鳌T赗ails中,動作是擴(kuò)展自ActionController的類;Struts中,動作是擴(kuò)展自Action的類。兩個前端控制器之間的主要區(qū)別是它們?nèi)绾螞Q定處理具體請求的動作。

??????????????????????????????????? 圖3 Ruby on Rails與Struts+Hibernate堆棧的比較
Rails根據(jù)請求的URL發(fā)現(xiàn)適當(dāng)?shù)膭幼?。圖4顯示,URL http://localhost/order/delete/4告訴Rails調(diào)用OrderController實例上的delete方法,并將4作為可用的實例變量。Rails知道/order將映射到文件order_controller.rb中定義的一個控制器類。如果在控制器中定義了find方法,那么只要用find替代URL中的delete,就可以調(diào)用這個方法。

??????????????????????????????????????? 圖4 Rails和Struts中的URL映射
Struts采用了不同的方式,開發(fā)人員需要把特定請求的映射外部化到XML配置文件中的Action類。當(dāng)首次裝入ActionServlet時,它將解析這個文件,并準(zhǔn)備接受請求。根據(jù)約定,以.do結(jié)束的請求被重定向到ActionServlet,由ActionServlet分派到適當(dāng)?shù)腁ction。圖4的XML是一個典型的映射,它告訴ActionServlet把叫作deleteOrder.do的請求轉(zhuǎn)發(fā)到controllers.order.DeleteOrderAction作進(jìn)一步處理。
3.2動作和模型
在Rails和Struts中,動作用來充當(dāng)前端控制器和模型之間的橋梁。開發(fā)人員提供動作的現(xiàn)實,從而提供特定于應(yīng)用程序的請求處理。前端控制器負(fù)責(zé)接受請求,并把請求傳遞到特定動作。圖5顯示了Rails和Struts基本的動作層次結(jié)構(gòu)。
在Rails中,必須擴(kuò)展ActionController::Base,讓模型參與到請求處理中。Rails沒有將ActionController的實例池化;相反,它為每個請求創(chuàng)建新的實例。雖然這對性能可能有負(fù)面影響,但是它可以讓開發(fā)變得更容易。開發(fā)人員不需要關(guān)注Struts中存在的線程問題,因此,會話、請求、標(biāo)題和參數(shù)都可以作為ActionController的實例成員來進(jìn)行訪問。
Struts要求開發(fā)人員擴(kuò)展Action并覆蓋execute(),以處理請求。通常,每個Action類都提供了非常具體的工作單元。圖5顯示了三個特定動作:SaveOrderAction、DeleteOrderAction和ListOrdersAction。前端控制器將調(diào)用execute()方法,傳遞給它許多有用的對象,其中包括HTTP請求和響應(yīng)對象。ActionForm是一個類,可以方便地向視圖來回傳輸并驗證與表單有關(guān)的輸入,ActionMapping包含映射的配置信息,就像圖4的XML所描述的那樣。execute()方法返回ActionForward對象,Struts用這個對象來確定對請求繼續(xù)進(jìn)行處理的組件。

??????????????????????????????????????? 圖5 Rails和Struts的動作層次結(jié)構(gòu)
3.3持久性框架
持久性框架用于在應(yīng)用程序?qū)雍蛿?shù)據(jù)庫之間交換數(shù)據(jù)。Rails和Hibernate的持久性框架都可以歸類為對象/關(guān)系映射(ORM)工具,它們接受數(shù)據(jù)的對象視圖,并將該視圖映射到關(guān)系數(shù)據(jù)庫內(nèi)的表中。使用兩種框架的目的都是為了減少與關(guān)系數(shù)據(jù)庫有關(guān)的開發(fā)時間。但是,圖6顯示了兩者在設(shè)計和配置上的一些區(qū)別。

???????????????????????????? ?圖6 ActiveRecord和Hibernate持久性框架的比較
Rails 的 ORM 框架叫作 Active Record,它基于同名的設(shè)計模式。Active Record 是包裝數(shù)據(jù)庫表或視圖中數(shù)據(jù)行的對象,封裝數(shù)據(jù)庫訪問,在數(shù)據(jù)上添加域邏輯。在 Rails 中,每個域?qū)ο蠖紝U(kuò)展提供 CRUD 操作的 ActiveRecord::Base。Active Record 不需要映射文件;實際上,使用 Active Record 的開發(fā)人員不需要對 getter 或 setter、甚至類的屬性進(jìn)行編碼。通過一些漂亮的詞匯分析,Active Record 能夠判斷出,Order 類將映射到數(shù)據(jù)庫中的 ORDERS 表。使用 Ruby 反射和元編程的組合,表的列可以變成對象的屬性。訪問器和調(diào)整器也添加了進(jìn)來。

圖7 order.rb?
圖7顯示了 Order 類的完成后的代碼。在 Order 類體中有一行代碼定義了它與 Item 對象的關(guān)系。has_many 是一個靜態(tài)方法調(diào)用,符號 :items 是它的參數(shù)。ActiveRecord 用 :items 發(fā)現(xiàn) Item 域?qū)ο?,然后將這個 Item 對象映射回數(shù)據(jù)庫中的 ITEMS 表。
Hibernate基于DataMapper模式,在這種模式中,特定的映射器類Session負(fù)責(zé)在數(shù)據(jù)庫中持久存儲和檢索數(shù)據(jù)。Hibernate可以持久存儲任何Java對象,只要這個對象符合JavaBean規(guī)范。XML映射文件描述了如何將類映射到數(shù)據(jù)庫中具體的表,并描述了類與其他類的關(guān)系。
圖8顯示了Hibernate映射文件的一個實例。class標(biāo)簽把Order對象映射到ORDERS表,還有許多子標(biāo)簽用于描述其屬性、ID訂單名稱,以及同models.Item的一對多關(guān)系。

?????????????????????????????????????????????????? 圖8 Order.hbm.xml
四、結(jié)束語
Ruby on Rails提供了開發(fā)Web 應(yīng)用程序的一種極其快捷的途徑,正在和已經(jīng)引起業(yè)界相當(dāng)?shù)呐d趣。它更傾向于清楚的代碼而不是配置文件,而Ruby語言的動態(tài)性質(zhì)在運(yùn)行時生成了大部分管道代碼。大多數(shù)Rails框架都是作為獨(dú)立項目創(chuàng)建的,而且應(yīng)用程序開發(fā)能夠從一組同類組件受益。相比之下,典型的J2EE架構(gòu)傾向于構(gòu)建在通常獨(dú)立開發(fā)的最好的組件之上,一般使用XML進(jìn)行配置并將組件組合在一起。
參考文獻(xiàn):
[1]吳吉義.基于Struts+Hibernate+Spring的電子政務(wù)應(yīng)用系統(tǒng)架構(gòu)[J].電子政務(wù),2005,(12):32-38.
[2]Rod Johnson.EXPERT ONE-ON-ONE J2EE DEVELOPMENT WITHOUT EJB[M].北京:電子工業(yè)出版社,2005.
[3]DAVE THOMAS, CHAD FOWLER, ANDY HUNT.PROGRAMMING RUBY: THE PRAGMATIC PROGRAMMERS' GUIDE[M].北京:電子工業(yè)出版社,2006.
[4]JAMES TURNER,KEVIN BEDELL.STRUTS KICK START[M].北京:電子工業(yè)出版社,2004.
[5]Aaron Rustad.Ruby on Rails and J2EE: Is there room for both?[EB/OL].
http://www-128.ibm.com/developerworks/web/library/wa-rubyonrails/, 2006-06-01/2006-07-15.
[6]David Mertz.Fast-track your Web apps with Ruby on Rails[EB/OL].
http://www-128.ibm.com/developerworks/linux/library/l-rubyrails/, 2006-06-01/2006-07-15.
