??xml version="1.0" encoding="utf-8" standalone="yes"?> U别: 高 Ruby on Rails 是一?Web 应用E序框架Q它的目标是为应用程序开发提供一条易行道。实际上Q框架的支持者们声称 Ruby on Rails 开发h员的生率最多是使用传统 J2EE 框架?10 倍。(请阅诠ZRolling with Ruby on Rails”一文,以获得关于这一声明的更多内容;请参?参考资?/A>Q。虽然这句话造成?Rails ?J2EE C相当大的争议Q但争论中却很少谈及(qing)如何比较 Rails ?J2EE 架构。本文将使用企业应用E序中常见的开源工P?Rails 框架和典型的 J2EE 实现q行比较?/P>
什么是 Ruby on RailsQ?/SPAN> 虽然我不能保证框架确实会(x)提供它所承诺的轻村ֿ乐,但是上面q句话确实很好地ȝ?Rails 的品质。全栈包括:(x)Web 服务器、处?HTTP h和响应的框架Q以?qing)方便地把数据持久存储到关系数据库的框架。Rails 通过消除复杂?XML 配置文gQ?Ruby 语言的动态性质Q帮助把?rn)态类型语a中常见的许多重复代码减少到最,努力使开发工作变得更Ҏ(gu)?/P>
Rails 和典型的 J2EE Web 堆栈 可以看到QRails 堆栈和构成普通的Z J2EE ?Web 应用E序的组件之间的基本区别很小。两者都有用来执行应用程序代码的容器Q都有帮助分d用程序的模型、视囑֒控g?MVC 框架Q以?qing)持久存储数据的机制?/P>
MVC 框架
技术架构师, Anassina, Inc.
2005 q?8 ?11 ?/P>
Ruby on Rails 是一个相对较新的 Web 应用E序框架Q构建在 Ruby 语言之上。它被宣传ؓ(f)现有企业框架的一个替代,而它的目标,而言之,是让生z,臛_?Web 开发方面的生活Q变得更L。在本文中,Aaron Rustad 对 Rails 和传l的 J2EE 框架在架构上的一些关键特性进行比较?/BLOCKQUOTE>
要想扑ֈ用一句话描述 Rails 的简单说明,只需查看目?主页 卛_Q?/P>
Rails 是一个用 Ruby ~写的全栈的Qfull-stackQ、开源的 Web 框架Q可以用它来轻杄写实际的应用E序Q所需的代码也要比大多数框架花在处?XML 上的代码?
?1 比较?Rails 堆栈和典型的 J2EE Web 堆栈Q包?Tomcat servlet 容器、Struts Web 应用E序框架?Hibernate 持久性框Ӟ(j)?/P>
模型-视图-控制器(MVCQ是应用旉相当ѝ应用面相当q的一个设计模式。它源自 SmalltalkQ如今,几乎所有的 GUI 框架Q包?Web 和胖客户端,都以该框架ؓ(f)基础。MVC 有三个部分:(x)模型Q负责业务逻辑Q包括应用程序状态和在q个状态上执行的动作;视图Q用来渲染和向用户呈现模型(?Web 应用E序中,视图一般渲染ؓ(f) HTMLQ;控制?/I>Q定义应用程序的行ؓ(f)。有?MVC 模式的详l解释,请参?参考资?/A>?/P>
前端控制?/SPAN>
Struts ?ActionServlet
?Rails ?DispatchServlet
都是前端控制器模式的例子Q所以,它们提供?jin)相同的功能。它们接?HTTP hQ解?URLQ把h的处理{发给适当的动作。在 Struts 中,动作是扩展自 Action
的类Q对?RailsQ动作是扩展?ActionController
的类。两个前端控制器之间的主要区别是它们如何军_处理具体h的动作?/P>
使用 StrutsQ开发h员需要把特定h的映外部化?XML 配置文g中的 Action
cR当首次装入 ActionServlet
Ӟ它将解析q个文gQƈ准备接受h。根据约定,?.do
l束的请求被重定向到 ActionServlet
Q由 ActionServlet 分派到适当?Action
?A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">?2 ?XML 是一个典型的映射。它告诉 ActionServlet
把叫?deleteOrder.do
的请求{发到 controllers.order.DeleteOrderAction
作进一步处理?/P>
Rails 采用?jin)不同的方式。它没有依赖配置文g把请求映到某一个动作,而是Ҏ(gu)h?URL 发现适当的动作。从?2 可以看到QURL http://localhost/order/delete/4
告诉 Rails 调用 OrderController
实例上的 delete
Ҏ(gu)Qƈ?4
作ؓ(f)可用的实例变量。Rails _聪明Q知?/order
映到文g order_controller.rb 中定义的一个控制器cR如果在控制器中定义?find
Ҏ(gu)Q那么只要用 find
替代 URL 中的 delete
Q就可以调用q个Ҏ(gu)?/P>
动作和模?/SPAN>
?Rails ?Struts 中,动作用来充当前端控制器和模型之间的桥梁。开发h员提供动作的现实Q从而提供特定于应用E序的请求处理。前端控制器负责接受hQƈ把请求传递到特定动作。图 3 演示?Rails ?Struts 基本的动作层ơ结构?/P>
动作是模型还是控制器Q?/B> |
Struts 要求开发h员扩?Action
q覆?execute()
Q以处理h。通常Q每?Action
c都提供?jin)非常具体的工作单元?A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">?3 演示?jin)三个特定动作?x)SaveOrderAction
?CODE>DeleteOrderAction ?ListOrdersAction
。前端控制器调?execute()
Ҏ(gu)Q传递给它许多有用的对象Q其中包?HTTP h和响应对象?CODE>ActionForm 是一个类Q它可以方便地向视图来回传输q证与表单有关的输入,ActionMapping
包含映射的配|信息,像 ?2 ?XML 所描述的那栗?/P>
execute()
Ҏ(gu)q回 ActionForward
对象QStruts 用这个对象来定对请求l进行处理的lg。一般来_(d)q个lg是一?JSP 面Q但?ActionForward
也能指向其他动作。开发h员必L楚,Struts 创徏的是 Action
的单一实例Qƈ允许多个U程调用它的 execute()
。这使请求处理变得更快,因ؓ(f)框架处理每个h时不用频J地创徏新的 Action
实例。但是因为可以在多个U程之间׃n单一对象Q所以必遵守适当的线E注意事,因ؓ(f)其他U程可能?x)破坏在q个动作中保持状态的实例变量?/P>
?Rails 中,必须扩展 ActionController::Base
Q让模型参与到请求处理中。Rails 没有?ActionController
的实例池化;相反Q它为每个请求创建新的实例。虽然这Ҏ(gu)能可能有负面媄(jing)响,但是它可以让开发变得更Ҏ(gu)。开发h员不需要关?Struts 中存在的U程问题Q因此,?x)话、请求、标题和参数都可以作?ActionController
的实例成员来q行讉K?CODE>ActionController q是一个将特定域逻辑的所有处理组合在一L(fng)合理场所。Struts ?Action
cLl粒度的Q它提供?jin)非常具体的工作单元Q?Rails ActionController
则是_粒度的Q它?yu)具体的工作单元模拟Z些方法?/P>
清单 1 ?清单 2 分别演示?jin)典型?Struts 动作和典型的 Rails 动作
?1 提供?jin)对两种?gu)的逻辑程的比较,q演CZ(jin)清单 1 和清?2 的特定行中发生的事情。研I?DeleteOrderAction
?execute()
Ҏ(gu)?OrderController
?delete
Ҏ(gu)Q可以看出它们基本上是相同的?/P>?1. execute() ?delete Ҏ(gu)比较
步骤 | Struts | Rails |
框架调用动作 | ?03Q?/B> execute() |
?07Q?/B> delete |
从请求中(g)索到?ID | ?06-07Q?/B>从请求对象中取出 | ?08Q?/B>从所有参数的实例哈希中取?/TD> |
从数据库删除订单记录 | ?09?4-24Q?/B>调用 delete() Ҏ(gu)Q用 Hibernate 删除记录 |
?09Q?/B>?ActiveRecord 删除记录 |
重定向到列出剩余订单 | ?11Q?/B>?ActionMapping 对象查找要转发处理的下一个组件?A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">?2 中的 XML 映射昄Q?CODE>success 映到 /listOrders Q这是另一?Action Q负责查扑։余订单,q以 JSP 的Ş式呈现它?/TD>
| ?10Q?/B>用将调用的下一动作的哈希来调用 redirect_to Ҏ(gu)Q在q种情况下,它只是调用同一控制器的 list Ҏ(gu) |
持久性框?/SPAN>
持久性框?/I> 用来在应用程序层和数据库之间来回Ud数据。Hibernate ?Rails 的持久性框架可以归cMؓ(f)对象/关系映射QORMQ工Pq意味着它们接受数据的对象视图,q将该视图映到关系数据库内的表中。用两U框架的目的都是Z(jin)减少与关pL据库有关的开发时间。但是,?4 演示?jin)两者在设计和配|上的一些根本区别?
?4. Active Record ?Hibernate 持久性框架的比较
Hibernate
Hibernate Z Data Mapper 模式Q在q种模式中,特定的映器c?Session
负责在数据库中持久存储和(g)索数据。Hibernate 可以持久存储M Java 对象Q只要这个对象符?JavaBean 规范。XML 映射文g描述?jin)如何将cL到数据库中具体的表Qƈ描述?jin)类与其他类的关pR?/P>
清单 3 昄?Hibernate 映射文g的一个实例?CODE>class 标签?Order
对象映射?ORDERS
表,q有许多子标{于描q其属性、ID 订单名称Q以?qing)?models.Item
的一对多关系?A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">清单 4 昄?Order
cLw?/P>清单 3. Order.hbm.xml
|
|
反射和元~程 以下代码实现反:(x)
q个代码实现元~程Q?/P>
|
Rails ?ORM 框架叫作 Active RecordQ它Z同名的设计模式。Martin Fowler ?Active Record 描述为“包装数据库表或视图中数据行的对象,装数据库访问,在数据上d域逻辑”。在 Rails 中,每个域对象都扩展提?CRUD 操作?ActiveRecord::Base
?/P>
?Hibernate 一PActive Record 不需要映文Ӟ实际上,使用 Active Record 的开发h员不需要对 getter ?setter、甚至类的属性进行编码。通过一些漂亮的词汇分析QActive Record 能够判断出,Order
cd映射到数据库中的 ORDERS
表。?Ruby 反射和元~程的组合,表的列可以变成对象的属性。访问器和调整器也添加了(jin)q来?/P>
清单 5 昄?Order
cȝ完成后的代码。在 Order
cM中有一行代码定义了(jin)它与 Item
对象的关pR?CODE>has_many 是一个静(rn)态方法调用,W号 :items
是它的参数。ActiveRecord ?:items
发现 Item
域对象,然后这?Item
对象映射回数据库中的 ITEMS
表?/P>清单 5. order.rb
|
?清单 5 那样~码?Order
cdq行时提供了(jin)一些类和实例方法。表 2 提供?jin)可?Order
上用的操作和属性的部分列表Q?
cL?/B> | 实例Ҏ(gu) | 属?/B> |
|
|
|
l束?/SPAN>
虽然 Ruby on Rails 是一个非常新、o(h)人兴奋的框架Qƈ且在 Web C中已l引起了(jin)Z相当的兴,但是它的核心(j)架构仍然遵@?J2EE 中发现的基本模式。开发把两个框架分开?Web 应用E序是一U合理的Ҏ(gu)。Rails 更喜Ƣ清楚的代码而不是配|文Ӟ?Ruby 语言的动态性质在运行时生成?jin)大部?I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">道 代码。大多数 Rails 框架都是作ؓ(f)独立目创徏的,而且应用E序开发能够从一l同cȝ件受益。相比之下,典型?J2EE 堆栈們于构建在通常独立开发的最好的lg之上Q常常用 XML q行配置q将lgl合在一赗?/P>
那么Q是否应该考虑对下一?Web 应用E序使用 Rails 呢?嗯,Z么不呢?它是~写得很好的lg堆栈Q它们彼此之间工作得很好Qƈ且基于行业接受的企业模式。Ruby 语言支持快速开发,q过生大多数应用程序管道来d到框架。熟(zhn)?Java 世界中的 MVC ?ORM 框架的h们在?Rails 表达自己的思想时没有Q何困难?/P>
?J2EE 一起分发会(x)不会(x)有利?RailsQ绝对不要。J2EE 是一个已l设|好的标准,有许多固定的实现Q而且Q最重要的是Q它是一个经q验证的技术。我(zhn)下载一?Rails 的副本,q开始自己钻研它。许多可用的教程都是介绍性的Q这些教E可以让(zhn)立卛_始?Rails。再ơ声明,我ƈ不能保证(zhn)会(x)通过使用 Rails 得到快乐Q但是我敢打赌?zhn)会(x)感到满意?/P>
关于作?/SPAN>![]() |