浏览 4489 次
锁定老帖子 主题:Groovy和Grails介绍(1)
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-02-18
诸如Ruby、PHP和Python之类的脚本语言最近几年越来越流行,因此,需要开发一个Java脚本备选语言和类似Rails的针对Java环境的框架。Groovy就是这个脚本语言,而Grails就是这个框架。 在本文中我将讨论Groovy的Web开发功能,然后继续讨论Grails框架。我将开发一个示例Grails Web应用程序,并讨论此框架的各种特性。 Groovy是什么? Groovy是一种语言,其语法类似于Java,但比Java更简单。它通常被视为脚本/灵活/动态的语言,但是我不喜欢这类形容词,因为我认为它们只会令人困惑。如果说Java是一位明智的中年男子,那么Groovy就是他十几岁的儿子。Groovy具有父亲的许多特点,但是更为狂野且更为有趣。他们也可以很好地合作。 Groovy的规则比Java少得多。例如,要在Java中获得标准的"Hello World"输出,您需要编写一个类、一个具有合适参数的主方法,等等。但是在Groovy中,如果不想编写所有样板代码,您可以抛开类定义和主方法,仅编写一行代码即可打印出"Hello World"。 以下是打印Hello World的文件 Hello.groovy 的内容: println "Hello World" Java平台仅关心使字节码得到执行。同样,此平台不强迫您使用Java语言。只要提供了字节码,工作就会进行。Groovy代码会被编译为字节码,而对于Java平台来说,字节码是从Java代码还是Groovy代码生成的并没有任何区别。 以下是一个Groovy例子,它显示了Groovy对清单、映射和范围的内置支持,并证明了Groovy的简单性及其利用Java的强大功能的能力: // 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()}" 请注意以上代码直接使用java.util.Date ,对收集的内置支持减少了使用清单、映射和范围所需的代码。还有许多其他有趣的Groovy特性,例如闭包和简化的XML处理。您可以在groovy.codehaus.org上找到详细清单。 现在让我们来讨论如何将Groovy用于Web开发。 使用Groovy进行Web开发 大多数Java EE教程都从一个基本servlet例子开始。对于Groovy Web开发来说,您将从groovlet(在groovy中servlet的对应概念)开始。如果您在servlet中摆脱了类和doXX() 方法声明,那么剩下的内容就与groovlet很像了。以下是一个名为 Login.groovy 的groovlet例子,您需要将它置于Web应用程序的最高级目录: def username= request.getParameter("username") def password= request.getParameter("password") if (username == "java" && password == "developer") { response.sendRedirect("home.jsp") session = request.getSession(true); session.setAttribute("name", username) } else { println """ <h1>Login Invalid</h1> <p>Your IP has been logged > ${request.remoteHost}</p> """ paramMap = request.getParameterMap() println "<p>You Submitted:</p>" for (entry in paramMap) { println "${entry.key} = ${entry.value}<br/>" } } 您可以仅创建一个简单的HTML表单,然后将此表单的行为属性发送到 action="Login.groovy"。然后将以下标签添加到web.xml: <servlet> <servlet-name>Groovy</servlet-name> <servlet-class>groovy.servlet.GroovyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Groovy</servlet-name> <url-pattern>*.groovy</url-pattern> </servlet-mapping> 现在只需将要求的Groovy jar 文件添加到WEB-INF/lib 目录,您的Groovy Web应用程序就准备好在任意Java EE应用服务器上运行了。 您应该已经注意到代码中没有分号,而且使用了隐式变量如request和response。其他隐式变量有context、application、session、out、sout和 html。 GSP是JSP在groovy中的对应概念。您无需使用println生成HTML;只需将Groovy代码嵌入HTML页面。本文中的例子将在提到Grails时使用GSP。 请注意,因为所有代码最终都要转换为字节码,所以groovlet和GSP能够与servlet和JSP轻松协作。因此您无需区分groovlet和GSP或者servlet和JSP。 现在让我们讨论前途无量的Grails框架。如果成功的话,Grails能够极大地改变开发Java Web应用程序的方式。Ruby on Rails对Ruby的影响,Grails也能够对Groovy实现。 Grails特性和架构 Grails试图使用Ruby On Rails的“规约编程”(coding by convention)范例来降低对配置文件和其他样板代码的需求。使用“规约编程” ,如果文件的名称本身就能说明此文件的用途,那么您就不需要在配置文件中再次声明这些内容了。此框架会查看文件名,并自己弄清文件用途。通过使用“规约编程” ,Grails还将自动生成Web应用程序中需要的许多内容。通过使用Grails,您将能够在很短的时间内、以最小的复杂性使Web应用程序就绪。请看以下例子。 Grails基于开源技术,例如Spring、Hibernate和 SiteMesh。如果您已经擅长这些技术,那么这是件好事;但是如果您由于某种原因不喜欢这些技术,或者您认为不仅需要学习Grails,还需要学习其他三种框架,那么这就不是件好事了。虽然这些技术能够帮助Grails执行得更好,但是学习四种框架对于大多数人来说是一个很高的门槛。Grails文档目前主要关注它与Spring、Hibernate和其他程序的集成,然而我认为它需要采用相反的方法,将Grails推行为一个简单快速的Web应用程序开发框架。开发人员无需担心或考虑底层发生了什么。 幸运的是,一旦您开始使用Grails,您将发现Grails隐藏了这些框架的大多数底层复杂性。如果您忘掉在底层运行的是Spring、Hibernate和其他程序,那么事情就会变得简单。 Grails应用程序的三个层是: 1. 由视图和控制器组成的Web层 2. 由域类和服务组成的业务逻辑层 3. 由域类和数据源组成的持久层 大多数框架都有数十种特性,其中只有很少几种得到了广泛使用。对于Grails来说,这种关键特性是指“规则编程”(coding by convention)范例和构件的自动生成。 Grails的其他特性包括对Ajax、验证、单元测试和功能测试的内置支持。它使用免费的开源Canoo WebTest项目来实现Web应用程序的功能测试。Grails还提供与Quartz Scheduler的集成。 现在是时候安装Grails框架并且编写您的第一个应用程序了。 Grails安装 安装过程非常简单。以下是Grails下载页面:http://grails.org/Download。您可以从http://dist.codehaus.org/grails/grails-bin-0.2.1.zip下载version 0.2.1。请注意Grails源代码和文档作为单独的下载提供。下载zip文件之后,只需将其内容解压缩到一个目录即可,在我的案例中此目录是 C:\groovy\grails-0.2.1\。 创建一个名为GRAILS_HOME 的新环境变量,并将其值设为 C:\groovy\grails-0.2.1\。接下来将GRAILS_HOME\bin 添加到PATH 环境变量。这样安装就完成了。通过在命令提示符界面中运行grails 命令您可以检查安装是否成功。您应该获得此命令的使用信息。 既然您有了一个运行中的Grails安装,那么您已经为创建Grails Web应用程序做好了准备。 开发Grails应用程序:应用程序结构 多年来我一直计划开发一个可以帮助我管理衣服的应用程序——这个应用程序应该能够告诉我我最喜欢的T恤衫放在哪里、是否洗过、是否熨过,等等。总有一天我会靠销售这个应用程序挣上几百万,但是现在我将把它用作Grails例子。 第一步是创建一个Grails项目目录结构。在这一步我将在C:\groovy\grailsapps 创建一个新目录,并在此级别打开一个命令提示符窗口。在此窗口中,执行命令grails create-app。要求您输入应用程序名称。输入 ClothesMgt。Grails将显示它为您创建的全部目录和文件。图1显示了最后得到的命令结构。 Groovy和Grails简介图-1 图1:Grails项目目录结构 此命令将创建约800 KB大小的文件和目录。这里的想法是此框架遵循已经建立的Web应用程序开发惯例,因此它创建的文件和目录在大多数Web应用程序中是有用的。虽然有些人可能不喜欢这种强制使用某种结构的想法,但是这种基于惯例的自动生成正是Grails的RAD特性的基础。 如果更仔细地看一下这些目录,您就会发现存在用于诸如控制器、视图、测试、配置文件和标签库之类东西的目录。您还会发现存在一些基本JavaScript和CSS文件。那么现在应用程序的基本结构已经有了。您只需做些填空,应用程序即可就绪。 请注意自动生成目录和文件的命令是可选的。您可以手动创建全部文件和目录。如果熟悉Apache Ant,那么您甚至可以打开GRAILS_HOME 目录中的\src\grails\build.xml 文件,来仔细查看每个Grails命令的用途。 数据库 在此例中我将使用一个运行于localhost的名为Clothes_Grails的MySQL数据库。Grails内置一个HSQL数据库,这对测试简单的应用程序或仅试用 Grails非常有用。如果您使用HSQL DB,那么无需执行以下几步。我将使用MySQL来证明您能够非常轻松地使用HSQL之外的数据库。 从http://www.mysql.com/products/connector/j/ 下载MySQL驱动器,并将mysql-connector-java-<version number>-stable-bin.jar 文件放置在ClothesMgt\lib 目录中。接下来您需要编辑 ClothesMgt\grails-app\conf\ApplicationDataSource.groovy文件。 现在此文件的内容应该类似以下内容: 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" } 现在让我们看一下如何使用此数据库和对象关系映射。 域类 Grails的对象关系映射(GORM)功能在内部使用Hibernate 3,但是您无需了解或更改任何Hibernate设置。Grails具有称为“域类”的东西,这些域类的对象被映射到数据库。您可以使用关系来链接域类,它们也提供用于CRUD(创建/读取/更新/删除)操作的功能非常强大的动态方法。 在此例中,我们将创建三个域类,其名称分别是Shirt、Trouser和Cabinet。要创建域类,只需运行命令 grails create-domain-class。请记住在您的项目目录(而不是它的上级目录)内运行此命令。这是一个常见错误,虽然我已经提醒了您,您还是会犯至少一次这样的错误。 您必须提供给 create-domain-class 命令的唯一输入是类的名称。运行此命令三次,将Shirt、Trouser和Cabinet作为三个域类的名称。Grails现在将在目录 grails-app/domain/中创建这些域类。它们将仅具有两个属性id 和 version。我将为这些类添加属性,以便使它们更能代表衬衫、裤子和衣橱。 清单1:Cabinet.groovy 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 >>> 32)) ) } } 清单2: Trouser.groovy 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 >>> 32) ) ) } } 清单3: Shirt.groovy 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 >>> 32))) } } 我添加的仅有的几行声明了字段名称和颜色,然后声明了Cabinet、Shirt和Trouser之间的关系。每个Shirt和Trouser都属于Cabinet,而Cabinet具有 shirt和trouser的集合。belongsTo 属性在此案例中是可选的,因为在一对多关系中,Grails会将“一”这一方视为所有者。因此您就无需显式声明了。在这里我进行显式声明只是为了使这种关系更明显。 接下来我们将讨论Grails应用程序的控制器和视图部分。 控制器和视图 既然域类已经就绪,让我们使用generate-all命令自动生成基本CRUD Web应用程序。运行grails generate-all 命令三次,当被询问时提供域类名称。generate-all 命令的目的是生成每个域类的控制器和视图,但是由于bug-245,Grails 0.2.1不能生成控制器。您必须手动生成控制器,其方法是对每个域类使用generate-controller 命令。 现在您应该在grails-app\controllers 目录中看到三个控制器。这些控制器负责处理Web应用程序中针对特定域类的请求。因此ShirtController.groovy 将处理Web应用程序中与Shirt域类相关的CRUD请求,等等。现在控制器具有多个闭包,每个闭包映射到一个URI。闭包是Groovy语言很好的一个特性,然而要习惯它还是需要一些时间的。清单4显示了Shirtcontroller.groovy的一段摘录。 清单4:ShirtController.groovy 摘录 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) } } // ... } 在此例中,ShirtController 中的list闭包将处理URI是/shirt/list的请求,等等。您可在控制器中使用您习惯在Java Web应用程序中使用的东西,例如请求、会话和servletContext。 请注意:闭包也将值作为显式返回语句返回,或者作为闭包体中的最后一个语句的值返回。不要因为Grails生成的代码中没有return 而困惑。 一旦控制器完成了对请求的处理,它必须委托给合适的视图。Grails使用惯例机制实现此操作。因此ShirtController 中的list闭包将委托给视图 /grails-app/views/shirt/list.gsp 或 /grails-app/views/shirt/list.jsp。尽管您在使用Grails,全部视图可以是JSP文件而不是GSP。我几乎没有编写任何代码,但是我已经准备好了一个Web应用程序。 让我们尝试部署和运行我们的应用程序。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-12-03
谢谢了,让我有了直观的了解
|
|
返回顶楼 | |
发表时间:2009-01-12
哈哈,看参考指南
|
|
返回顶楼 | |