﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-天生我才-文章分类-Ruby</title><link>http://www.blogjava.net/oscar-1981/category/7271.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 08:18:12 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 08:18:12 GMT</pubDate><ttl>60</ttl><item><title>Ruby on Rails 和 J2EE：两者能否共存？</title><link>http://www.blogjava.net/oscar-1981/articles/29888.html</link><dc:creator>天生我才</dc:creator><author>天生我才</author><pubDate>Wed, 08 Feb 2006 02:05:00 GMT</pubDate><guid>http://www.blogjava.net/oscar-1981/articles/29888.html</guid><wfw:comment>http://www.blogjava.net/oscar-1981/comments/29888.html</wfw:comment><comments>http://www.blogjava.net/oscar-1981/articles/29888.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/oscar-1981/comments/commentRss/29888.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/oscar-1981/services/trackbacks/29888.html</trackback:ping><description><![CDATA[<SPAN class=atitle2>两个 Web 应用程序框架的比较</SPAN><BR>
<TABLE border=0 cellPadding=0 cellSpacing=0>
<TBODY>
<TR align=left vAlign=top>
<TD>
<P>级别: 高级</P></TD></TR></TBODY></TABLE>
<P><A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#author1"><NAME>Aaron Rustad</NAME></A><BR>技术架构师, Anassina, Inc.<BR>2005 年 8 月 11 日</P>
<BLOCKQUOTE>Ruby on Rails 是一个相对较新的 Web 应用程序框架，构建在 Ruby 语言之上。它被宣传为现有企业框架的一个替代，而它的目标，简而言之，就是让生活，至少是 Web 开发方面的生活，变得更轻松。在本文中，Aaron Rustad 将对 Rails 和传统的 J2EE 框架在架构上的一些关键特性进行比较。</BLOCKQUOTE>
<P>Ruby on Rails 是一个 Web 应用程序框架，它的目标是为应用程序开发提供一条易行道。实际上，框架的支持者们声称 Ruby on Rails 开发人员的生产率最多是使用传统 J2EE 框架的 10 倍。（请阅读“Rolling with Ruby on Rails”一文，以获得关于这一声明的更多内容；请参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>）。虽然这句话造成了 Rails 和 J2EE 社区相当大的争议，但争论中却很少谈及如何比较 Rails 和 J2EE 架构。本文将使用企业应用程序中常见的开源工具，对 Rails 框架和典型的 J2EE 实现进行比较。</P>
<P><A name=1><SPAN class=atitle2>什么是 Ruby on Rails？</SPAN></A><BR>要想找到用一句话描述 Rails 的简单说明，只需查看项目的 <A href="http://www.rubyonrails.org/" target=_new xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">主页</A> 即可：</P>
<BLOCKQUOTE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Rails 是一个用 Ruby 编写的全栈的（full-stack）、开源的 Web 框架，可以使用它来轻松编写实际的应用程序，所需的代码也要比大多数框架花在处理 XML 上的代码少。 </BLOCKQUOTE>
<P>虽然我不能保证框架确实会提供它所承诺的轻松快乐，但是上面这句话确实很好地总结了 Rails 的品质。全栈包括：Web 服务器、处理 HTTP 请求和响应的框架，以及方便地把数据持久存储到关系数据库的框架。Rails 通过消除复杂的 XML 配置文件，使用 Ruby 语言的动态性质，帮助把静态类型语言中常见的许多重复代码减少到最少，努力使开发工作变得更容易。</P>
<P><A name=1.1><SPAN class=atitle3>Rails 和典型的 J2EE Web 堆栈</SPAN></A><BR>图 1 比较了 Rails 堆栈和典型的 J2EE Web 堆栈（包括 Tomcat servlet 容器、Struts Web 应用程序框架和 Hibernate 持久性框架）。</P>
<P><A name=figure1><B>图 1. Rails 和 J2EE 堆栈的比较 </B></A><BR><IMG alt="Rails 和 J2EE 堆栈的比较" height=248 src="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/stack.jpg" width=599 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>可以看到，Rails 堆栈和构成普通的基于 J2EE 的 Web 应用程序的组件之间的基本区别很小。两者都有用来执行应用程序代码的容器；都有帮助分离应用程序的模型、视图和控件的 MVC 框架；以及持久存储数据的机制。</P>
<P>
<TABLE align=right border=1 cellPadding=5 cellSpacing=0 width="45%">
<TBODY>
<TR>
<TD background=/developerworks/cn/i/bg-gold.gif>
<P><A name=sidebar1><B>MVC 框架</B></A><BR>模型-视图-控制器（MVC）是应用时间相当长、应用面相当广的一个设计模式。它源自 Smalltalk；如今，几乎所有的 GUI 框架，包括 Web 和胖客户端，都以该框架为基础。MVC 有三个部分：<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">模型</I>，负责业务逻辑，包括应用程序状态和将在这个状态上执行的动作；<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">视图</I>，用来渲染和向用户呈现模型（在 Web 应用程序中，视图一般渲染为 HTML）；<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">控制器</I>，定义应用程序的行为。有关 MVC 模式的详细解释，请参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>。</P></TD></TR></TBODY></TABLE></P>
<P><A name=1.2><SPAN class=atitle3>前端控制器</SPAN></A><BR>Struts 的 <CODE>ActionServlet</CODE> 和 Rails 的 <CODE>DispatchServlet</CODE> 都是前端控制器模式的例子；所以，它们提供了相同的功能。它们接受 HTTP 请求，解析 URL，把请求的处理转发给适当的动作。在 Struts 中，动作是扩展自 <CODE>Action</CODE> 的类；对于 Rails，动作是扩展自 <CODE>ActionController</CODE> 的类。两个前端控制器之间的主要区别是它们如何决定处理具体请求的动作。</P>
<P>使用 Struts，开发人员需要把特定请求的映射外部化到 XML 配置文件中的 <CODE>Action</CODE> 类。当首次装入 <CODE>ActionServlet</CODE> 时，它将解析这个文件，并准备接受请求。根据约定，以 <CODE>.do</CODE> 结束的请求被重定向到 <CODE>ActionServlet</CODE>，由 ActionServlet 分派到适当的 <CODE>Action</CODE>。<A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#figure2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 2</A> 的 XML 是一个典型的映射。它告诉 <CODE>ActionServlet</CODE> 把叫作 <CODE>deleteOrder.do</CODE> 的请求转发到 <CODE>controllers.order.DeleteOrderAction</CODE> 作进一步处理。</P>
<P>Rails 采用了不同的方式。它没有依赖配置文件把请求映射到某一个动作，而是根据请求的 URL 发现适当的动作。从图 2 可以看到，URL <CODE>http://localhost/order/delete/4</CODE> 告诉 Rails 调用 <CODE>OrderController</CODE> 实例上的 <CODE>delete</CODE> 方法，并将 <CODE>4</CODE> 作为可用的实例变量。Rails 足够聪明，知道 <CODE>/order</CODE> 将映射到文件 order_controller.rb 中定义的一个控制器类。如果在控制器中定义了 <CODE>find</CODE> 方法，那么只要用 <CODE>find</CODE> 替代 URL 中的 <CODE>delete</CODE>，就可以调用这个方法。</P>
<P><A name=figure2><B>图 2. Rails 和 Struts 中的 URL 映射 </B></A><BR><IMG alt="Rails 和 Struts 中的 URL 映射" height=211 src="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/mappings.jpg" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=1.3><SPAN class=atitle3>动作和模型</SPAN></A><BR>在 Rails 和 Struts 中，动作用来充当前端控制器和模型之间的桥梁。开发人员提供动作的现实，从而提供特定于应用程序的请求处理。前端控制器负责接受请求，并把请求传递到特定动作。图 3 演示了 Rails 和 Struts 基本的动作层次结构。</P>
<P><A name=figure3><B>图 3. Rails 和 Struts 的动作层次结构</B></A><BR><IMG alt="Rails 和 Struts 的动作层次结构" height=200 src="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/actions.jpg" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P>
<TABLE align=right border=1 cellPadding=5 cellSpacing=0 width="45%">
<TBODY>
<TR>
<TD background=/developerworks/cn/i/bg-gold.gif>
<P><A name=sidebar2><B>动作是模型还是控制器？</B></A><BR><CODE>Action</CODE> 和 <CODE>ActionController</CODE> 从技术上讲是 MVC 模式的控制器的一部分，因为它们对客户发起的事件进行响应。但是，在小型应用程序中，开发人员通常在这些类中对域或业务逻辑进行编码，所以在这些情况下，也可以把它们看作是模型的一部分。最佳实践建议：应当把域逻辑从控制器中抽象出来，放置在它自己的特定于域的类中。</P></TD></TR></TBODY></TABLE></P>
<P>Struts 要求开发人员扩展 <CODE>Action</CODE> 并覆盖 <CODE>execute()</CODE>，以处理请求。通常，每个 <CODE>Action</CODE> 类都提供了非常具体的工作单元。<A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#figure3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 3</A> 演示了三个特定动作：<CODE>SaveOrderAction</CODE>、<CODE>DeleteOrderAction</CODE> 和 <CODE>ListOrdersAction</CODE>。前端控制器将调用 <CODE>execute()</CODE> 方法，传递给它许多有用的对象，其中包括 HTTP 请求和响应对象。<CODE>ActionForm</CODE> 是一个类，它可以方便地向视图来回传输并验证与表单有关的输入，<CODE>ActionMapping</CODE> 包含映射的配置信息，就像 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#figure2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 2</A> 的 XML 所描述的那样。</P>
<P><CODE>execute()</CODE> 方法返回 <CODE>ActionForward</CODE> 对象，Struts 用这个对象来确定对请求继续进行处理的组件。一般来说，这个组件是一个 JSP 页面，但是 <CODE>ActionForward</CODE> 也能指向其他动作。开发人员必须清楚，Struts 创建的是 <CODE>Action</CODE> 的单一实例，并允许多个线程调用它的 <CODE>execute()</CODE>。这使请求处理变得更快，因为框架处理每个请求时不用频繁地创建新的 <CODE>Action</CODE> 实例。但是因为可以在多个线程之间共享单一对象，所以必须遵守适当的线程注意事项，因为其他线程可能会破坏在这个动作中保持状态的实例变量。</P>
<P>在 Rails 中，必须扩展 <CODE>ActionController::Base</CODE>，让模型参与到请求处理中。Rails 没有将 <CODE>ActionController</CODE> 的实例池化；相反，它为每个请求创建新的实例。虽然这对性能可能有负面影响，但是它可以让开发变得更容易。开发人员不需要关注 Struts 中存在的线程问题，因此，会话、请求、标题和参数都可以作为 <CODE>ActionController</CODE> 的实例成员来进行访问。<CODE>ActionController</CODE> 还是一个将特定域逻辑的所有处理组合在一起的合理场所。Struts 的 <CODE>Action</CODE> 类是细粒度的，它提供了非常具体的工作单元，而 Rails <CODE>ActionController</CODE> 则是粗粒度的，它将具体的工作单元模拟为一些方法。</P>
<P><A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/listing1.html" target=_new xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">清单 1</A> 和 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/listing2.html" target=_new xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">清单 2</A> 分别演示了典型的 Struts 动作和典型的 Rails 动作</P>
<P>表 1 提供了对两种方法的逻辑流程的比较，并演示了清单 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/listing1.html" target=_new xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1</A> 和清单 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/listing2.html" target=_new xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2</A> 的特定行中发生的事情。研究 <CODE>DeleteOrderAction</CODE> 的 <CODE>execute()</CODE> 方法和 <CODE>OrderController</CODE> 的 <CODE>delete</CODE> 方法，可以看出它们基本上是相同的。</P><A name=table1><B>表 1. execute() 和 delete 方法比较</B></A><BR>
<TABLE border=1 cellPadding=3 cellSpacing=1 width="80%">
<TBODY>
<TR align=middle vAlign=top>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">步骤</B></TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Struts</B></TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Rails</B></TD></TR>
<TR>
<TD>框架调用动作</TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 03：</B> <CODE>execute()</CODE></TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 07：</B> <CODE>delete</CODE></TD></TR>
<TR>
<TD>从请求中检索到的 ID </TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 06-07：</B>从请求对象中取出</TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 08：</B>从所有参数的实例哈希中取出</TD></TR>
<TR>
<TD>从数据库删除订单记录</TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 09、14-24：</B>调用 <CODE>delete()</CODE> 方法，用 Hibernate 删除记录</TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 09：</B>用 ActiveRecord 删除记录</TD></TR>
<TR>
<TD>重定向到列出剩余订单</TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 11：</B>用 <CODE>ActionMapping</CODE> 对象查找将要转发处理的下一个组件。<A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#figure2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 2</A> 中的 XML 映射显示，<CODE>success</CODE> 将映射到 <CODE>/listOrders</CODE>，这是另一个 <CODE>Action</CODE>，负责查找剩余订单，并以 JSP 的形式呈现它们</TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">行 10：</B>用将调用的下一动作的哈希来调用 <CODE>redirect_to</CODE> 方法；在这种情况下，它只是调用同一控制器的 <CODE>list</CODE> 方法</TD></TR></TBODY></TABLE>
<P><A name=2><SPAN class=atitle2>持久性框架</SPAN></A><BR><I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">持久性框架</I> 用来在应用程序层和数据库之间来回移动数据。Hibernate 和 Rails 的持久性框架可以归类为对象/关系映射（ORM）工具，这意味着它们接受数据的对象视图，并将该视图映射到关系数据库内的表中。使用两种框架的目的都是为了减少与关系数据库有关的开发时间。但是，<A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#figure4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">图 4</A> 演示了两者在设计和配置上的一些根本区别。 </P>
<P><A name=figure4><B>图 4. Active Record 和 Hibernate 持久性框架的比较 </B></A><BR><IMG alt=" Active Record 和 Hibernate 持久性框架的比较" height=206 src="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/persistence.jpg" width=600 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> </P>
<P><A name=2.1><SPAN class=atitle3>Hibernate</SPAN></A><BR>Hibernate 基于 Data Mapper 模式，在这种模式中，特定的映射器类 <CODE>Session</CODE> 负责在数据库中持久存储和检索数据。Hibernate 可以持久存储任何 Java 对象，只要这个对象符合 JavaBean 规范。XML 映射文件描述了如何将类映射到数据库中具体的表，并描述了类与其他类的关系。</P>
<P><A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#listing3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">清单 3</A> 显示了 Hibernate 映射文件的一个实例。<CODE>class</CODE> 标签把 <CODE>Order</CODE> 对象映射到 <CODE>ORDERS</CODE> 表，还有许多子标签用于描述其属性、ID 订单名称，以及同 <CODE>models.Item</CODE> 的一对多关系。<A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#listing4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">清单 4</A> 显示了 <CODE>Order</CODE> 类本身。</P><A name=listing3><B>清单 3. Order.hbm.xml</B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE>

...
01 &lt;hibernate-mapping&gt;
02    &lt;class name="models.Order" table="ORDERS"
03        dynamic-update="true" dynamic-insert="false"
04        discriminator-value="null"&gt;
05
06 	&lt;id name="id" column="id" type="java.lang.Long" 
07             unsaved-value="null"&gt;
08             &lt;generator class="identity"/&gt;
09         &lt;/id&gt;
10 
11         &lt;set name="items" lazy="false" inverse="false"
12            cascade="none" sort="unsorted"&gt;
13             &lt;key column="id"/&gt;
14             &lt;one-to-many class="models.Item"/&gt;
15         &lt;/set&gt;
16 
17         &lt;property name="name" type="java.lang.String"
18             update="true" insert="true"
19             access="property" column="name"/&gt;
20     &lt;/class&gt;
21 &lt;/hibernate-mapping&gt;
</CODE></PRE></TD></TR></TBODY></TABLE><A name=listing4><B>清单 4. Order.java</B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE>

01 public class Order {
02    private Set items;
03     private String name;
04     private Long id;
05 
06     public Long getId() { return id;}
07 
08     public void setId(Long id) { this.id = id;}
09 	
10     public Set getItems() { return items;}
11 	
12     public void setItems(Set items) { this.items = items; }
13 	
14     public String getName() { return name; }
15 
16     public void setName(String name) { this.name = name; }
17 }
</CODE></PRE></TD></TR></TBODY></TABLE>
<P><A name=2.2><SPAN class=atitle3>Active Record</SPAN></A><BR></P>
<P>
<TABLE align=right border=1 cellPadding=5 cellSpacing=0 width="45%">
<TBODY>
<TR>
<TD background=/developerworks/cn/i/bg-gold.gif>
<P><A name=sidebar3><B>反射和元编程</B></A><BR>Wikipedia 中（请参阅 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#resources" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">参考资料</A>）简要地把 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">反射</I> 定义为“程序在运行的时候检查和修改其高级结构的能力”。在那里，还将 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">元编程</I> 定义为“编写那些能够编写和操作其他其他程序（或它们自己），将其他程序作为自己的数据的程序，或者编写那些完成其他程序在运行时所做的部分工作的程序。”</P>
<P>以下代码将实现反射：</P>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE>
01 obj = "some_string"
02 if obj.respond_to?('length'):
03   puts "obj length = #{obj.length}" 
03 end
&gt;&gt; obj length = 5
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>这个代码将实现元编程：</P>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><PRE><CODE>
01 class SomeClass
02 end
03 newMethod = %q{def msg() puts "A message!" end}
04 SomeClass.class_eval(newMethod)
05 aClass = SomeClass.new
06 aClass.msg
&gt;&gt; A message!
</CODE></PRE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></P>
<P>Rails 的 ORM 框架叫作 <I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Active Record</I>，它基于同名的设计模式。Martin Fowler 将 Active Record 描述为“包装数据库表或视图中数据行的对象，封装数据库访问，在数据上添加域逻辑”。在 Rails 中，每个域对象都将扩展提供 CRUD 操作的 <CODE>ActiveRecord::Base</CODE>。</P>
<P>与 Hibernate 一样，Active Record 不需要映射文件；实际上，使用 Active Record 的开发人员不需要对 getter 或 setter、甚至类的属性进行编码。通过一些漂亮的词汇分析，Active Record 能够判断出，<CODE>Order</CODE> 类将映射到数据库中的 <CODE>ORDERS</CODE> 表。使用 Ruby 反射和元编程的组合，表的列可以变成对象的属性。访问器和调整器也添加了进来。</P>
<P><A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#listing5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">清单 5</A> 显示了 <CODE>Order</CODE> 类的完成后的代码。在 <CODE>Order</CODE> 类体中有一行代码定义了它与 <CODE>Item</CODE> 对象的关系。<CODE>has_many</CODE> 是一个静态方法调用，符号 <CODE>:items</CODE> 是它的参数。ActiveRecord 用 <CODE>:items</CODE> 发现 <CODE>Item</CODE> 域对象，然后将这个 <CODE>Item</CODE> 对象映射回数据库中的 <CODE>ITEMS</CODE> 表。</P><A name=listing5><B>清单 5. order.rb</B></A><BR>
<TABLE bgColor=#cccccc border=1 cellPadding=5 cellSpacing=0 width="40%">
<TBODY>
<TR>
<TD><PRE><CODE>

01 class Order &lt; ActiveRecord::Base
02	has_many :items
03 end
</CODE></PRE></TD></TR></TBODY></TABLE>
<P>像 <A href="http://www-128.ibm.com/developerworks/cn/java/wa-rubyonrails/#listing5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">清单 5</A> 那样编码的 <CODE>Order</CODE> 类在运行时提供了一些类和实例方法。表 2 提供了可在 <CODE>Order</CODE> 上使用的操作和属性的部分列表： </P><A name=table2><B>表 2. 在 Order 上可用的属性和操作</B></A><BR>
<TABLE border=1 cellPadding=3 cellSpacing=1 width="80%">
<TBODY>
<TR align=middle vAlign=top>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">类方法</B></TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">实例方法</B></TD>
<TD><B xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">属性</B></TD></TR>
<TR vAlign=top>
<TD>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI><CODE>find(*args)</CODE> 
<LI><CODE>find_by_sql(sql)</CODE> 
<LI><CODE>exists?(id)</CODE> 
<LI><CODE>create(attributes)</CODE> 
<LI><CODE>update(id, attributes)</CODE> 
<LI><CODE>update_all(updates, conditions</CODE> 
<LI><CODE>delete(id)</CODE> 
<LI><CODE>delete_all(conditions)</CODE> 
<LI>... </LI></UL></TD>
<TD>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI><CODE>add_items</CODE> 
<LI><CODE>build_to_items</CODE> 
<LI><CODE>create_in_items</CODE> 
<LI><CODE>find_all_in_items</CODE> 
<LI><CODE>find_in_items</CODE> 
<LI><CODE>has_items?</CODE> 
<LI><CODE>items</CODE> 
<LI><CODE>items=</CODE> 
<LI><CODE>items_count</CODE> 
<LI><CODE>remove_items</CODE> </LI></UL></TD>
<TD>
<UL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<LI><CODE>id</CODE> 
<LI><CODE>name</CODE> </LI></UL></TD></TR></TBODY></TABLE>
<P><A name=3><SPAN class=atitle2>结束语</SPAN></A><BR>虽然 Ruby on Rails 是一个非常新、令人兴奋的框架，并且在 Web 社区中已经引起了人们相当的兴趣，但是它的核心架构仍然遵循在 J2EE 中发现的基本模式。开发把两个框架分开的 Web 应用程序是一种合理的方法。Rails 更喜欢清楚的代码而不是配置文件，而 Ruby 语言的动态性质在运行时生成了大部分<I xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">管道</I> 代码。大多数 Rails 框架都是作为独立项目创建的，而且应用程序开发能够从一组同类组件受益。相比之下，典型的 J2EE 堆栈倾向于构建在通常独立开发的最好的组件之上，常常用 XML 进行配置并将组件组合在一起。</P>
<P>那么，是否应该考虑对下一个 Web 应用程序使用 Rails 呢？嗯，为什么不呢？它是编写得很好的组件堆栈，它们彼此之间工作得很好，并且基于行业接受的企业模式。Ruby 语言支持快速开发，并通过生产大多数应用程序管道来添加到框架。熟悉 Java 世界中的 MVC 和 ORM 框架的人们在用 Rails 表达自己的思想时没有任何困难。</P>
<P>与 J2EE 一起分发会不会有利于 Rails？绝对不要。J2EE 是一个已经设置好的标准，有许多固定的实现，而且，最重要的是，它是一个经过验证的技术。我建议您下载一份 Rails 的副本，并开始自己钻研它。许多可用的教程都是介绍性的，这些教程可以让您立即开始使用 Rails。再次声明，我并不能保证您会通过使用 Rails 得到快乐，但是我敢打赌您会感到满意。</P>
<P><A name=resources><SPAN class=atitle2>参考资料 </SPAN></A>
<UL>
<LI>您可以参阅本文在 developerWorks 全球站点上的 <A href="http://www-128.ibm.com/developerworks/web/library/wa-rubyonrails/" target=_blank xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">英文原文</A>。<BR><BR>
<LI>请参阅 <A href="http://www.rubyonrails.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Ruby on Rails Web site</A>。<BR><BR>
<LI>从 <A href="http://www.ruby-lang.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">ruby-lang.org</A> 得到关于 Ruby 的您需要了解的最新信息。<BR><BR>
<LI>发现更多关于 <A href="http://struts.apache.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Struts</A> 和 <A href="http://jakarta.apache.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Jakarta project</A> 的信息。<BR><BR>
<LI>学习更多关于 <A href="http://www.hibernate.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Hibernate</A> 的知识。<BR><BR>
<LI>从 Curt Hibbs 撰写的“<A href="http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Rolling with Ruby on Rails</A>”（ONLamp.com，2005 年 1 月）得到一份关于创建 Rails 应用程序的好的介绍。<BR><BR>
<LI>在 Sun 的 <A href="http://java.sun.com/reference/blueprints/index.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Blueprints</A> 目录中寻找 <A href="http://java.sun.com/blueprints/patterns/MVC-detailed.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Model-View-Controller</A> 和 <A href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Front Controller</A> 模式的简要解释说明。<BR><BR>
<LI>在 <A href="http://www.martinfowler.com/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Martin Fowler's Web site</A> 上了解对 <A href="http://www.martinfowler.com/eaaCatalog/activeRecord.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Active Record</A> 和 <A href="http://www.martinfowler.com/eaaCatalog/dataMapper.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Data Mapper</A> 模式精简后的解释。<BR><BR>
<LI>掌握 <A href="http://www.ibm.com/developerworks/web/library/l-rubyrails/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Fast-track your Web apps with Ruby on Rails</A>，这样就可以用这个基于 Ruby 的框架和它的模型-视图-控制器设计模式来迅速构建和定制应用程序（developerWorks，2005 年 6 月）。<BR><BR>
<LI>从 <A href="http://www.ibm.com/developerworks/web/library/l-ruby1.html" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Programming in the Ruby language</A>（developerWorks, 2001 年 7 月）开始研究 Ruby 和它的变量、引用、数组、对象和方法。<BR><BR>
<LI>在 <A href="http://www-128.ibm.com/developerworks/cn/java/j-struts/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Struts，MVC 的一种开放源码实现</A> 中研究 Struts 如何帮助控制 Web 项目中的变化，并提高您的专长（developerWorks，2001 年 2 月）。<BR><BR>
<LI>在 <A href="http://www.ibm.com/developerworks/web/library/j-hibern/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Object-relation mapping without the container</A> 中，学习结合使用 Hibernate 和 Spring，为企业应用程序构建事务性的持久存储层（developerWorks，2004 年 4 月）。<BR><BR>
<LI>请参 Wikipedia 的关于 <A href="http://en.wikipedia.org/wiki/Reflection_%28computer_science%29" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">reflection</A> 和 <A href="http://en.wikipedia.org/wiki/Metaprogramming_%28programming%29" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">metaprogramming</A> 定义。<BR><BR>
<LI>请参阅 developerWorks <A href="http://www.ibm.com/developerworks/web/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Web Architecture</A> 专区，获得介绍各种基于 Web 的解决方案的文章。<BR><BR>
<LI>通过参与 <A href="http://www.ibm.com/developerworks/blogs/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">developerWorks blogs</A> 加入 developerWorks 社区。<BR></LI></UL>
<P></P>
<TABLE border=0 cellPadding=0 cellSpacing=0 width="100%">
<TBODY>
<TR>
<TD><A name=author1></A><SPAN class=atitle2>关于作者</SPAN><BR><IMG align=left alt="Aaron Rustad 的照片" height=80 name="Aaron Rustad" src="http://www.ibm.com/developerworks/i/p-arustad.jpg" width=64 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Aaron Rustad 从 1998 年起就一直从事 Java 技术的工作，并且一直是适用于一些垂直市场的 J2EE 应用程序的架构师和开发人员，这些垂直市场包括石油天然气、农业和教育。您可以通过 <A href="mailto:arustad@gmail.com?subject=Rails and J2EE Architectures Compared&amp;cc:htc@us.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">arustad@gmail.com</A> 与 Aaron 联系。 </TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/oscar-1981/aggbug/29888.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/oscar-1981/" target="_blank">天生我才</a> 2006-02-08 10:05 <a href="http://www.blogjava.net/oscar-1981/articles/29888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>