﻿<?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-cAng^Er-随笔分类-|:相关开源:|</title><link>http://www.blogjava.net/xiaosao/category/24839.html</link><description>不懂我的人 , 离不了我 , 该了解了解我 !而懂我的人 , 更离不了我 , 因为他们爱我 。</description><language>zh-cn</language><lastBuildDate>Thu, 21 Feb 2008 18:59:59 GMT</lastBuildDate><pubDate>Thu, 21 Feb 2008 18:59:59 GMT</pubDate><ttl>60</ttl><item><title>Groovy和Grails简介</title><link>http://www.blogjava.net/xiaosao/archive/2008/02/21/181031.html</link><dc:creator>cAng^Er</dc:creator><author>cAng^Er</author><pubDate>Thu, 21 Feb 2008 04:40:00 GMT</pubDate><guid>http://www.blogjava.net/xiaosao/archive/2008/02/21/181031.html</guid><wfw:comment>http://www.blogjava.net/xiaosao/comments/181031.html</wfw:comment><comments>http://www.blogjava.net/xiaosao/archive/2008/02/21/181031.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaosao/comments/commentRss/181031.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaosao/services/trackbacks/181031.html</trackback:ping><description><![CDATA[<h3>转载：原文地址 http://dev2dev.bea.com.cn/techdoc/200601194089.html</h3>
<h3>摘要</h3>
<p>　　Java Web应用程序框架是企业Java得以成功的重要原因之一。人们怀疑如果没有Apache Struts框架Java EE是否能够如此成功。虽然底层编程语言很重要，但通常是框架使编程语言成为引人注目的中心的。如果您经常访问讨论论坛，就会注意到Ruby语言和Ruby On Rails框架之间也是这种情况。Ruby已经出现十多年了，然而只是在Ruby On Rails框架流行之后，开发人员才开始注意到Ruby语言。</p>
<p>　　诸如Ruby、PHP和Python之类的脚本语言最近几年越来越流行，因此，需要开发一个Java脚本备选语言和类似Rails的针对Java环境的框架。Groovy就是这个脚本语言，而Grails就是这个框架。</p>
<p>　　在本文中我将讨论Groovy的Web开发功能，然后继续讨论Grails框架。我将开发一个示例Grails Web应用程序，并讨论此框架的各种特性。</p>
<h3>Groovy是什么？</h3>
<p>　　<a href="http://groovy.codehaus.org/" target="_blank">Groovy</a>是一种语言，其语法类似于Java，但比Java更简单。它通常被视为脚本/灵活/动态的语言，但是我不喜欢这类形容词，因为我认为它们只会令人困惑。如果说Java是一位明智的中年男子，那么Groovy就是他十几岁的儿子。Groovy具有父亲的许多特点，但是更为狂野且更为有趣。他们也可以很好地合作。</p>
<p>　　Groovy的规则比Java少得多。例如，要在Java中获得标准的"Hello World"输出，您需要编写一个类、一个具有合适参数的主方法，等等。但是在Groovy中，如果不想编写所有样板代码，您可以抛开类定义和主方法，仅编写一行代码即可打印出"Hello World"。</p>
<p>　　以下是打印Hello World的文件 Hello.groovy 的内容：</p>
<pre class="code">println "Hello World" </pre>
<p>　　Java平台仅关心使字节码得到执行。同样，此平台不强迫您使用Java语言。只要提供了字节码，工作就会进行。Groovy代码会被编译为字节码，而对于Java平台来说，字节码是从Java代码还是Groovy代码生成的并没有任何区别。</p>
<p>　　以下是一个Groovy例子，它显示了Groovy对清单、映射和范围的内置支持，并证明了Groovy的简单性及其利用Java的强大功能的能力：</p>
<pre class="code">// Print Date
def mydate = new java.util.Date()
println mydate
//Iterate through a map
def numbersMAP = ['1':'ONE', '2':'TWO']
for (entry in numbersMAP) {
println "${entry.key} = ${entry.value}"
}
//Introducing the range
def range = 'a'..'d'
//Lists
def numberlist = [1, 2, 3, 4, 5, 6, 7, 8]
println numberlist;
println "Maximum value: ${numberlist.max()}"
</pre>
<p>　　请注意以上代码直接使用java.util.Date ，对收集的内置支持减少了使用清单、映射和范围所需的代码。还有许多其他有趣的Groovy特性，例如闭包和简化的XML处理。您可以在<a href="http://groovy.codehaus.org/" target="_blank">groovy.codehaus.org</a>上找到详细清单。</p>
<p>　　现在让我们来讨论如何将Groovy用于Web开发。</p>
<h3>使用Groovy进行Web开发</h3>
<p>　　大多数Java EE教程都从一个基本servlet例子开始。对于Groovy Web开发来说，您将从groovlet（在groovy中servlet的对应概念）开始。如果您在servlet中摆脱了类和doXX() 方法声明，那么剩下的内容就与groovlet很像了。以下是一个名为 Login.groovy 的groovlet例子，您需要将它置于Web应用程序的最高级目录：</p>
<pre class="code">def username= request.getParameter("username")
def password= request.getParameter("password")
if (username == "java" &amp;&amp; password == "developer") {
response.sendRedirect("home.jsp")
session = request.getSession(true);
session.setAttribute("name", username)
}
else {
println """
&lt;h1&gt;Login Invalid&lt;/h1&gt;
&lt;p&gt;Your IP has been logged &gt; ${request.remoteHost}&lt;/p&gt;
"""
paramMap = request.getParameterMap()
println "&lt;p&gt;You Submitted:&lt;/p&gt;"
for (entry in paramMap) {
println "${entry.key} = ${entry.value}&lt;br/&gt;"
}
}
</pre>
<p>　　您可以仅创建一个简单的HTML表单，然后将此表单的行为属性发送到 action="Login.groovy"。然后将以下标签添加到web.xml：</p>
<pre class="code">&lt;servlet&gt;
&lt;servlet-name&gt;Groovy&lt;/servlet-name&gt;
&lt;servlet-class&gt;groovy.servlet.GroovyServlet&lt;/servlet-class&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;Groovy&lt;/servlet-name&gt;
&lt;url-pattern&gt;*.groovy&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
</pre>
<p>　　现在只需将要求的Groovy jar 文件添加到WEB-INF/lib 目录，您的Groovy Web应用程序就准备好在任意Java EE应用服务器上运行了。</p>
<p>　　您应该已经注意到代码中没有分号，而且使用了隐式变量如request和response。其他隐式变量有context、application、session、out、sout和 html。</p>
<p>　　GSP是JSP在groovy中的对应概念。您无需使用println生成HTML；只需将Groovy代码嵌入HTML页面。本文中的例子将在提到Grails时使用GSP。</p>
<p>　　请注意，因为所有代码最终都要转换为字节码，所以groovlet和GSP能够与servlet和JSP轻松协作。因此您无需区分groovlet和GSP或者servlet和JSP。</p>
<p>　　现在让我们讨论前途无量的Grails框架。如果成功的话，Grails能够极大地改变开发Java Web应用程序的方式。Ruby on Rails对Ruby的影响，Grails也能够对Groovy实现。</p>
<h3>Grails特性和架构</h3>
<p>　　Grails试图使用Ruby On Rails的&#8220;规约编程&#8221;（coding by convention）范例来降低对配置文件和其他样板代码的需求。使用&#8220;规约编程&#8221; ，如果文件的名称本身就能说明此文件的用途，那么您就不需要在配置文件中再次声明这些内容了。此框架会查看文件名，并自己弄清文件用途。通过使用&#8220;规约编程&#8221; ，Grails还将自动生成Web应用程序中需要的许多内容。通过使用Grails，您将能够在很短的时间内、以最小的复杂性使Web应用程序就绪。请看以下例子。</p>
<p>　　Grails基于开源技术，例如Spring、Hibernate和SiteMesh。如果您已经擅长这些技术，那么这是件好事；但是如果您由于某种原因不喜欢这些技术，或者您认为不仅需要学习Grails，还需要学习其他三种框架，那么这就不是件好事了。虽然这些技术能够帮助Grails执行得更好，但是学习四种框架对于大多数人来说是一个很高的门槛。Grails文档目前主要关注它与Spring、Hibernate和其他程序的集成，然而我认为它需要采用相反的方法，将Grails推行为一个简单快速的Web应用程序开发框架。开发人员无需担心或考虑底层发生了什么。</p>
<p>　　幸运的是，一旦您开始使用Grails，您将发现Grails隐藏了这些框架的大多数底层复杂性。如果您忘掉在底层运行的是Spring、Hibernate和其他程序，那么事情就会变得简单。</p>
<p>　　<a href="http://grails.org/Advanced+Topics" target="_blank">Grails应用程序的三个层</a>是：</p>
<ol>
    <li>由视图和控制器组成的Web层
    <li>由域类和服务组成的业务逻辑层
    <li>由域类和数据源组成的持久层 </li>
</ol>
<p>　　大多数框架都有数十种特性，其中只有很少几种得到了广泛使用。对于Grails来说，这种关键特性是指&#8220;规则编程&#8221;（coding by convention）范例和构件的自动生成。</p>
<p>　　Grails的其他特性包括对Ajax、验证、单元测试和功能测试的内置支持。它使用免费的开源Canoo WebTest项目来实现Web应用程序的功能测试。Grails还提供与Quartz Scheduler的集成。</p>
<p>　　现在是时候安装Grails框架并且编写您的第一个应用程序了。</p>
<h3>Grails安装</h3>
<p>　　安装过程非常简单。以下是Grails下载页面：<a href="http://grails.codehaus.org/Download" target="_blank">http://grails.org/Download</a>。您可以从<a href="http://dist.codehaus.org/grails/grails-bin-0.2.1.zip">http://dist.codehaus.org/grails/grails-bin-0.2.1.zip</a>下载version 0.2.1。请注意Grails源代码和文档作为单独的下载提供。下载zip文件之后，只需将其内容解压缩到一个目录即可，在我的案例中此目录是 C:\groovy\grails-0.2.1\。</p>
<p>　　创建一个名为GRAILS_HOME 的新环境变量，并将其值设为 C:\groovy\grails-0.2.1\。接下来将GRAILS_HOME\bin 添加到PATH 环境变量。这样安装就完成了。通过在命令提示符界面中运行grails 命令您可以检查安装是否成功。您应该获得此命令的使用信息。</p>
<p>　　既然您有了一个运行中的Grails安装，那么您已经为创建Grails Web应用程序做好了准备。</p>
<h3>开发Grails应用程序：应用程序结构</h3>
<p>　　多年来我一直计划开发一个可以帮助我管理衣服的应用程序——这个应用程序应该能够告诉我我最喜欢的T恤衫放在哪里、是否洗过、是否熨过，等等。总有一天我会靠销售这个应用程序挣上几百万，但是现在我将把它用作Grails例子。</p>
<p>　　第一步是创建一个Grails项目目录结构。在这一步我将在C:\groovy\grailsapps 创建一个新目录，并在此级别打开一个命令提示符窗口。在此窗口中，执行命令grails create-app。要求您输入应用程序名称。输入 ClothesMgt。Grails将显示它为您创建的全部目录和文件。图1显示了最后得到的命令结构。</p>
<p align="center"><img height="400" alt="Groovy和Grails简介图-1" src="http://dev2dev.bea.com.cn/images/image061226001.gif" width="124" border="0" /></p>
<p>　　图1：Grails项目目录结构</p>
<p>　　此命令将创建约800 KB大小的文件和目录。这里的想法是此框架遵循已经建立的Web应用程序开发惯例，因此它创建的文件和目录在大多数Web应用程序中是有用的。虽然有些人可能不喜欢这种强制使用某种结构的想法，但是这种基于惯例的自动生成正是Grails的RAD特性的基础。</p>
<p>　　如果更仔细地看一下这些目录，您就会发现存在用于诸如控制器、视图、测试、配置文件和标签库之类东西的目录。您还会发现存在一些基本JavaScript和CSS文件。那么现在应用程序的基本结构已经有了。您只需做些填空，应用程序即可就绪。</p>
<p>　　请注意自动生成目录和文件的命令是可选的。您可以手动创建全部文件和目录。如果熟悉Apache Ant，那么您甚至可以打开GRAILS_HOME 目录中的\src\grails\build.xml 文件，来仔细查看每个Grails命令的用途。</p>
<h3>数据库</h3>
<p>　　在此例中我将使用一个 运行于localhost的名为Clothes_Grails的MySQL数据库。Grails内置一个HSQL数据库，这对测试简单的应用程序或仅试用Grails非常有用。如果您使用HSQL DB，那么无需执行以下几步。我将使用MySQL来证明您能够非常轻松地使用HSQL之外的数据库。</p>
<p>　　从<a href="http://www.mysql.com/products/connector/j/" target="_blank">http://www.mysql.com/products/connector/j/</a> 下载MySQL驱动器，并将mysql-connector-java-&lt;version number&gt;-stable-bin.jar 文件放置在ClothesMgt\lib 目录中。接下来您需要编辑 ClothesMgt\grails-app\conf\ApplicationDataSource.groovy文件。</p>
<p>　　现在此文件的内容应该类似以下内容：</p>
<pre class="code">class ApplicationDataSource {
boolean pooling = true
String dbCreate = "create-drop"
String url = "jdbc:mysql://localhost/Clothes_Grails"
String driverClassName = "com.mysql.jdbc.Driver"
String username = "grails"
String password = "groovy"
}
</pre>
<p>　　现在让我们看一下如何使用此数据库和对象关系映射。</p>
<h3>域类</h3>
<p>　　Grails的对象关系映射(GORM)功能在内部使用Hibernate 3，但是您无需了解或更改任何Hibernate设置。Grails具有称为&#8220;域类&#8221;的东西，这些域类的对象被映射到数据库。您可以使用关系来链接域类，它们也提供用于CRUD（创建/读取/更新/删除）操作的功能非常强大的动态方法。</p>
<p>　　在此例中，我们将创建三个域类，其名称分别是Shirt、Trouser和Cabinet。要创建域类，只需运行命令 grails create-domain-class。请记住在您的项目目录（而不是它的上级目录）内运行此命令。这是一个常见错误，虽然我已经提醒了您，您还是会犯至少一次这样的错误。</p>
<p>　　您必须提供给create-domain-class 命令的唯一输入是类的名称。运行此命令三次，将Shirt、Trouser和Cabinet作为三个域类的名称。Grails现在将在目录 grails-app/domain/中创建这些域类。它们将仅具有两个属性id 和 version。我将为这些类添加属性，以便使它们更能代表衬衫、裤子和衣橱。</p>
<p>　　<em>清单1：Cabinet.groovy</em></p>
<pre class="code">class Cabinet {
Long id
Long version
String name
String location
def relatesToMany = [ shirts : Shirt, trousers : Trouser ]
Set shirts = new HashSet()
Set trousers = new HashSet()
String toString() { "${this.class.name} :  $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Cabinet)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id &gt;&gt;&gt; 32)) )
}
}
</pre>
<p>　　<em>清单2： Trouser.groovy</em></p>
<pre class="code">class Trouser {
Long id
Long version
String name
String color
Cabinet cabinet
def belongsTo = Cabinet
String toString() { "${this.class.name} :  $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Trouser)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id &gt;&gt;&gt; 32) ) )
}
}
</pre>
<p>　　<em>清单3： Shirt.groovy</em></p>
<pre class="code">class Shirt {
Long id
Long version
String name
String color
Cabinet cabinet
def belongsTo = Cabinet
String toString() { "${this.class.name} :  $id" }
boolean equals(other) {
if(other?.is(this))return true
if(!(other instanceof Shirt)) return false
if(!id || !other?.id || id!=other?.id) return false
return true
}
int hashCode() {
int hashCode = 0
hashCode = 29 * (hashCode + ( !id ? 0 : id ^ (id &gt;&gt;&gt; 32)))
}
}
</pre>
<p>　　我添加的仅有的几行声明了字段名称和颜色，然后声明了Cabinet、Shirt和Trouser之间的关系。每个Shirt和Trouser都属于Cabinet，而Cabinet具有shirt和trouser的集合。belongsTo 属性在此案例中是可选的，因为在一对多关系中，Grails会将&#8220;一&#8221;这一方视为所有者。因此您就无需显式声明了。在这里我进行显式声明只是为了使这种关系更明显。</p>
<p>　　接下来我们将讨论Grails应用程序的控制器和视图部分。</p>
<h3>控制器和视图</h3>
<p>　　既然域类已经就绪，让我们使用generate-all命令自动生成基本CRUD Web应用程序。运行grails generate-all 命令三次，当被询问时提供域类名称。generate-all 命令的目的是生成每个域类的控制器和视图，但是由于<a href="http://jira.codehaus.org/browse/GRAILS-245" target="_blank">bug-245</a>，Grails 0.2.1不能生成控制器。您必须手动生成控制器，其方法是对每个域类使用generate-controller 命令。</p>
<p>　　现在您应该在grails-app\controllers 目录中看到三个<a href="http://grails.codehaus.org/Controllers" target="_blank">控制器</a>。这些控制器负责处理Web应用程序中针对特定域类的请求。因此ShirtController.groovy 将处理Web应用程序中与Shirt域类相关的CRUD请求，等等。现在控制器具有多个闭包，每个闭包映射到一个URI。<a href="http://groovy.codehaus.org/Closures" target="_blank">闭包</a>是Groovy语言很好的一个特性，然而要习惯它还是需要一些时间的。清单4显示了Shirtcontroller.groovy的一段摘录。</p>
<p>　　<em>清单4：ShirtController.groovy 摘录</em></p>
<pre class="code">class ShirtController {
def index = { redirect(action:list,params:params) }
def list = {
[ shirtList: Shirt.list( params ) ]
}
def show = {
[ shirt : Shirt.get( params.id ) ]
}
def delete = {
def shirt = Shirt.get( params.id )
if(shirt) {
shirt.delete()
flash.message = "Shirt ${params.id} deleted."
redirect(action:list)
}
else {
flash.message = "Shirt not found with id ${params.id}"
redirect(action:list)
}
}
// ...
}
</pre>
<p>　　在此例中，ShirtController 中的list闭包将处理URI是/shirt/list的请求，等等。您可在控制器中使用您习惯在Java Web应用程序中使用的东西，例如请求、会话和servletContext。</p>
<p>　　<strong>请注意：</strong>闭包也将值作为显式<em>返回</em>语句返回，或者作为闭包体中的最后一个语句的值返回。不要因为Grails生成的代码中没有return 而困惑。</p>
<p>　　一旦控制器完成了对请求的处理，它必须委托给合适的视图。Grails使用惯例机制实现此操作。因此ShirtController 中的list闭包将委托给视图 /grails-app/views/shirt/list.gsp 或 /grails-app/views/shirt/list.jsp。 尽管您在使用Grails，全部视图可以是JSP文件而不是GSP。我几乎没有编写任何代码，但是我已经准备好了一个Web应用程序。</p>
<p>　　让我们尝试部署和运行我们的应用程序。</p>
<h3>在Java EE Server上部署和运行Grails</h3>
<p>　　Grails具有一个内置Resin服务器，您可使用grails run-app 命令运行应用程序。此命令会将应用程序部署到Resin服务器并启动服务器。因此您现在可以在<em>http://localhost:8080/ClothesMgt</em> 访问此应用程序。您还可以同样轻松地将应用程序部署到任意JavaEE服务器。我尝试将它部署到Tomcat。要实现此操作，我所需要做的是运行grails war 命令，将生成的war文件复制到Tomcat中的<em>webapps目录！</em></p>
<p>　　在此案例中生成的war文件的名称为 ClothesMgt.war。一旦部署到Tomcat，您就应该能够在http://localhost:8080/ClothesMgt/ 上访问它，并看到如图2所示的屏幕。</p>
<p align="center"><img height="389" alt="Groovy和Grails简介图-2" src="http://dev2dev.bea.com.cn/images/image061226002.gif" width="458" border="0" /></p>
<p>　　<em>图2：Grails 应用程序</em></p>
<p>　　通过此应用程序，能够获得Shirt、Trouser和Cabinet的全部CRUD功能。可以显示衣橱的全部数据、向衣橱添加新衬衫和裤子、编辑它们的值和删除记录——实现这些操作都无需编写任何业务逻辑、视图或数据访问代码。仅在几分钟内您就在JavaEE服务器上部署好了一个合适的Web应用程序。很酷吧？！</p>
<p>　　让我们更进一步来定制Grails。</p>
<h3>创建自定义控制器</h3>
<p>　　我现在将把新功能和页面添加到Web应用程序，同时重用已经存在的域类。shirt/list 和 trouser/list 会分别显示衬衫和裤子的清单，现在让我们添加一个新的显示，来同时显示衬衫和裤子的清单。要创建一个新的显示，您需要一个新的控制器和视图。</p>
<p>　　使用 generate-controller 和 generate-views 命令，可以轻松实现使用域类自动生成视图和控制器。然而，在此案例中我希望创建一个与域类不直接关联的控制器。因此我将使用grails create-controller命令。当被提示输入控制器名称时，声明Display。Grails将在grails-app/controllers/ 目录创建一个名为DisplayController.groovy 的控制器，在grails-tests 目录创建一个测试套件。如清单5所示编辑控制器。</p>
<p>　　<em>清单5：DisplayController.groovy</em></p>
<pre class="code">class DisplayController {
def index = {redirect(action:list,params:params)}
def list = {
params['max'] = 10
return [ shirtList: Shirt.list( params ),
trouserList: Trouser.list( params )]
}
}
</pre>
<p>　　index 闭包将请求重定向到清单。在list 闭包中我将最大参数设为10，然后使用动态方法Shirt.list 和 Trouser.list。然后返回<a href="http://groovy.codehaus.org/Collections">Groovy Map</a>，它有两个清单——衬衫清单和裤子清单。</p>
<p>　　作为Java开发人员，当看到Shirt.list()时会自然认为是在Shirt域类中的list 方法。然而，如果打开Shirt.groovy，会发现并没有此方法。对于Java开发人员来说，不了解Groovy的特性就使用Grails不仅是令人困惑的，而且是死胡同。动态方法是Grails的特殊特性，它是构建于Groovy语言的一个非常特殊的特性<a href="http://www.indicthreads.com/interviews/429/groovy_grails_scripting_enterprise_java.html">元对象协议</a> (MOP)之上的。如此证明可以使用动态方法查询域类。因此，在控制器中，您将注意到在域类上调用的方法似乎在域类中不存在。您可以在<a href="http://grails.org/GORM#GORM-DomainClassQuerying">这里</a>阅读关于使用动态方法查询的更多信息。可以在<a href="http://grails.org/Dynamic+Methods+Reference">这里</a>找到对Grails控制器和域类中可用的动态方法的参考资料。</p>
<p>　　既然控制器能够处理请求、获取清单并转发到视图，我需要创建相应视图。</p>
<h3>创建自定义视图</h3>
<p>　　当创建控制器时，Grails还在grails-app\views 目录创建了一个新的<em>显示</em>目录，并将以下映射添加到web.xml 文件中。</p>
<pre class="code">&lt;servlet-mapping&gt;
&lt;servlet-name&gt;grails&lt;/servlet-name&gt;
&lt;url-pattern&gt;/display/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
</pre>
<p>　　目前Grails有一个generate-views 命令，此命令能够生成基于域类的视图，然而没有能够自动生成视图的create-view 命令。请看图3中的例子。</p>
<p align="center"><img height="372" alt="Groovy和Grails简介图-3" src="http://dev2dev.bea.com.cn/images/image061226003.gif" width="458" border="0" /></p>
<p>　　<em>图3：一个显示Trousers的默认视图</em></p>
<p>　　因为我希望创建一个独立于域类的视图，所以让我们手动创建视图文件。在目录grails-app\views\display\中，创建一个名为 list.gsp的文件，如清单6所示。</p>
<p>　　<em>清单6：list.gsp</em></p>
<pre class="code">&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/&gt;
&lt;title&gt;Display Shirt And Trouser List&lt;/title&gt;
&lt;link rel="stylesheet" href="${createLinkTo(dir:'css',file:'main.css')}"&gt;&lt;/link&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="nav"&gt;
&lt;span class="menuButton"&gt;&lt;a href="${createLinkTo(dir:'')}"&gt;Home&lt;/a&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="body"&gt;
&lt;h1&gt;Shirt List&lt;/h1&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Id&lt;/th&gt;&lt;th&gt;Cabinet&lt;/th&gt; &lt;th&gt;Color&lt;/th&gt;&lt;th&gt;Name&lt;/th&gt;
&lt;/tr&gt;
&lt;g:each in="${shirtList}"&gt;
&lt;tr&gt;
&lt;td&gt;${it.id}&lt;/td&gt; &lt;td&gt;${it.cabinet.name}&lt;/td&gt;
&lt;td&gt;${it.color}&lt;/td&gt; &lt;td&gt;${it.name}&lt;/td&gt;
&lt;/tr&gt;
&lt;/g:each&gt;
&lt;/table&gt;
&lt;h1&gt;Trouser List&lt;/h1&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;th&gt;Id&lt;/th&gt; &lt;th&gt;Cabinet&lt;/th&gt;
&lt;th&gt;Color&lt;/th&gt; &lt;th&gt;Name&lt;/th&gt;
&lt;/tr&gt;
&lt;g:each in="${trouserList}"&gt;
&lt;tr&gt;
&lt;td&gt;${it.id}&lt;/td&gt; &lt;td&gt;${it.cabinet.name}&lt;/td&gt;
&lt;td&gt;${it.color}&lt;/td&gt; &lt;td&gt;${it.name}&lt;/td&gt;
&lt;/tr&gt;
&lt;/g:each&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>　　与我之前使用的方式类似，您现在也可以使用run-app 命令运行应用程序，或者创建一个war文件并将其部署到Tomcat。您应该在<em>http://localhost:8080/ClothesMgt/display/</em>下看到新的视图，如图4所示。</p>
<p align="center"><img height="383" alt="Groovy和Grails简介图-4" src="http://dev2dev.bea.com.cn/images/image061226004.gif" width="458" border="0" /></p>
<p>　　<em>图4：新创建的列出衬衫和裤子清单的视图</em></p>
<p>　　现在让我们快速讨论一下Grails服务。</p>
<h3>服务</h3>
<p>　　如果您想知道如何分开业务逻辑以及放置业务逻辑的位置，答案在<a href="http://grails.org/Services">Grails 服务</a>中。服务以SomeNameService.groovy 格式命名，且被置于 /grails-app/services/目录。服务可利用依赖注入特性，您能够轻松地从控制器内部调用这些服务。</p>
<p>　　让我们来看一个使用服务的例子。首先，使用create-service 命令创建新服务。运行此命令并命名服务Order。Grails将创建两个文件——grails-app/services/OrderService.groovy 和 grails-tests/OrderTests.groovy。</p>
<p>　　现在编辑OrderService.groovy，如清单7所示。当引入新的orderGoods() 方法时会自动生成serviceMethod() 。</p>
<p>　　<em>清单7：OrderService.groovy</em></p>
<pre class="code">class OrderService {
boolean transactional = true
def serviceMethod() {
// TODO
}
def orderGoods() {
return "Order Placed - New shirts and trousers \
will be sent shortly."
}
}
</pre>
<p>　　现在编辑DisplayController，如清单8所示。引入使用OrderService的重排闭包。请注意服务将由Groovy注入。</p>
<p>　　<em>清单8：DisplayController.groovy</em></p>
<pre class="code">class DisplayController {
OrderService orderService
def index = {redirect(action:list,params:params)}
def list = {
params['max'] = 10
return [ shirtList: Shirt.list( params )
, trouserList: Trouser.list( params )]
}
def reorder = {
render(orderService.orderGoods())
}
}
</pre>
<p>　　现在当您访问URL http://localhost:8080/ClothesMgt/display/reorder时，重排闭包将调用 OrderService，响应会被发回到浏览器。您能够以类似方式将全部业务逻辑移入服务，然后使用Grails的注入功能非常轻松地使用它们。</p>
<h3>动态方法和属性</h3>
<p>　　正如之前提到的，域类没有能够从数据库获取数据或更新/删除现有数据的任何方法，例如find()、 findAll() 或 save() 。在控制器中您也没有编写诸如 redirect() 或 render() 之类的方法。但是域类和控制器有它们的计划目的，且允许所有要求的操作。原因是Grails中<a href="http://grails.org/Dynamic+Methods+Reference" target="_blank">动态方法和属性</a>的存在。动态方法被动态添加到类，就好像功能是在程序中编译的一样。</p>
<p>　　这些是可用的方法和属性，无需编写。这些动态方法涵盖了大多数Web应用程序开发中会碰到的常见情况。对于域类来说，存在诸如find()、findAll()、list()、executeQuery()、save()和 delete()之类的动态方法。控制器具有诸如session、request和response之类的动态属性，以及诸如chain()、render()和 redirect()之类的方法。要真正利用Grails的强大功能，您需要了解所有这些动态方法和属性的功能。</p>
<h3>顺便介绍一下：自动重载和@Property</h3>
<p>　　Grails的一个重要特性是能够在开发过程中进行了更改时自动重载文件。因此只需编辑和保存gsp文件，就会自动重载新文件。然而这里创建的类似OrderService 的事务服务不会被重载。您会在服务器控制台看到以下消息<em>"[groovy] Cannot reload class [class OrderService] reloading of transactional service classes is not currently possible. Set class to non-transactional first. "</em>。</p>
<p>　　Grails的自动重载功能会为您节省许多时间，您就无需浪费时间来重启服务器了。我碰到过一些Grails不能自动重载的案例，例如将一个jsp文件重命名到gsp。然而，Grails的这项功能有望在未来版本中得到进一步改进。</p>
<p>　　在Groovy JSR 06 的之前版本中，您必须使用@Property 来定义Groovy中的新属性。因此您会在线看到许多使用@Property的旧的Groovy例子。然而请注意，@Property已经从Groovy JSR 06中移除，在Grails 0.2和之后的版本中也不会再需要它。请参阅<a href="http://docs.codehaus.org/display/GroovyJSR/Property+proposal" target="_blank">@Property 建议</a>来获得更多细节。</p>
<h3>结束语</h3>
<p>　　在本文中，我介绍了Grails框架的基本特性，并使用Grails创建了一个应用程序。Groovy和Grails最大的好处是一切都运行在优秀的旧Java和Java EE上——因此您能够使用Groovy和Grails的RAD特性快速开发应用程序，然后将应用程序部署到可靠的Java EE服务器上。考虑到关于Ruby和Rails的宣传噪音，显然需要一个Java备选方案。Groovy和Grails看起来非常适合这个角色。</p>
<h3>下载</h3>
<p>　　下载本文中的代码：</p>
<ul>
    <li><a href="http://dev2dev.bea.com/2006/10/Dev2Dev_ClothesMgt_Code.zip">本文中的代码</a> (zip)。
    <li>最新版本的<a href="http://clothesmanager.googlecode.com/svn/trunk/" target="_blank">SVN快照</a>。 </li>
</ul>
<h3>参考资料</h3>
<ul>
    <li><a href="http://grails.org/" target="_blank">Grails</a>主页
    <li><a href="http://groovy.codehaus.org/" target="_blank">Groovy</a>主页
    <li><a href="http://docs.codehaus.org/display/GRAILS/Home" target="_blank">Grails Wiki</a>
    <li><a href="http://grails.codehaus.org/Mailing+lists" target="_blank">Grails Mailing 清单</a>
    <li><a href="http://www.onjava.com/pub/a/onjava/2004/09/29/groovy.html" target="_blank">Groovy, Java's New Scripting Language</a> (ONJava, 2004)
    <li><a href="http://java.sun.com/developer/technicalArticles/JavaLP/groovy/" target="_blank">Getting to Know Groovy</a> (Sun, 2005)
    <li><a href="http://www.indicthreads.com/interviews/429/groovy_grails_scripting_enterprise_java.html" target="_blank">Groovy bridges the scripting and the enterprise Java worlds</a> (IndicThreads, 2006) </li>
</ul>
<img src ="http://www.blogjava.net/xiaosao/aggbug/181031.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaosao/" target="_blank">cAng^Er</a> 2008-02-21 12:40 <a href="http://www.blogjava.net/xiaosao/archive/2008/02/21/181031.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>