Grails 开发说明

紧随 Ruby on Rails (RoR) 潮流,大多数软件开发人员已开始考虑使用 ROR 或提供 ROR 功能的其他框架(如果尚未使用的话)。

借着 Rails 的东风,Grails 框架也受到了广泛欢迎,但现在它已凭借自身实力发展成为一个功能强大的框架。

Grails 使用 Groovy 编程语言;Groovy 语法与 Java 类似,但它还采用了其他语言中的某些概念。

与 Java 一样,Groovy 生成字节码并在 Java 平台上运行,因此它不但具有 Java 的功能,而且更简单、更准确。

Speaker 和 Paper

Grails 提供了一个功能强大的 GORM(Grails 对象关系映射)形式的持久性机制,此机制基于 Hibernate 对象关系持久性。因此,开发人员可以创建域类并定义这些域类之间的关系。持久性由 GORM 实现。

域类位于大多数使用 Grails 开发的数据驱动 Web 应用程序的核心。域类为特殊类,不仅因为它们所包含的关系、规则和逻辑,而且因为 Grails 在运行时注入这些域类中的功能。我们将在应用程序中创建两个域类(Speaker 和 Paper)并查看其功能。在此示例中,域类的设计非常简单,且未标准化成更小的单元,但您可以很容易地将其标准化,方法是创建新的域类并设置这些域类之间的关系(就像在 Speaker 和 Paper 之间设置的关系一样)。

要创建域类,需要使用 Grails 命令 create-domain-class。您将在 Oracle JDeveloper 中创建新的外部工具,所用命令行与先前创建的工具相同。下面是唯一不同的几个地方:
Program executable:${env:var=GRAILS_HOME}\bin\grails.bat
Arguments:create-domain-class ${promptl:label=Name}
Run directory:${project.dir}

运行 create-domain-class 工具。在提示符下输入 Speaker。将创建新文件 /grails-app/domain/Speaker.groovy。接下来,创建 Paper 域类。也会在域目录中创建 Paper.groovy 文件。现在您需要定义 Speaker 和 Paper 的属性以及二者的关系。

在 Oracle JDeveloper 中打开 Speaker.groovy。如果运行 Oracle JDeveloper 10.1.3 并安装了 Groovy 插件,将显示标记 .groovy 文件的图标。按如下所示编辑 Speaker.groovy 文件。[code]class Speaker {

// Fields

String userid

String password

String fname

String lname

String address1

String address2

String city

String state

String country

String bio

String company

String speakingExp

String email

String phone

String mobile

//default values

String status = “active”

Date lastLoginDate = new Date()

Date registerDate = new Date()

// Optional - Can be null

def optionals = [ “status”, “address2”, “company”,“mobile”, “speakingExp”]

// One speaker has many papers

static hasMany = [papers:Paper]

// Constraints used for validations

static constraints = {

userid(size:5…10,unique:true)

password(size:5…10)

fname(size:1…30)

lname(size:1…30)

email(email:true)

phone(size:6…15)

city(size:1…20)

state(size:1…20)

country(size:1…20)

address1(size:5…200)

bio(size:10…1000)

}

}[/code]在 Speaker 类中,您定义了希望演讲者提供的信息的属性、可以为空的字段、需要验证的属性的约束条件,以及 Speaker 和 Paper 类之间的关系。单词 optionals、hasMany 和 constraints 是 Grails 提供的特殊设置。在此示例中,由于 hasMany 设置,Grails 会将 java.util.Set 类型的属性注入 Speaker 中。

接下来,修改 Paper.groovy,如下所示。[code]class Paper {

// Fields

String title

String description

String comments

String status = “active”

Date lastModifiedDate = new Date()

Date createdDate = new Date()

Speaker speaker

//Every paper belongs to a speaker

def belongsTo = Speaker

static constraints = {

title(size:5…200)

description(minSize:10, maxSize:2000)

}

def optionals = [ “comments”, “status”]

}[/code]belongsTo 属性通知 Grails 每张论文都属于某个演讲者。因此,如果删除该演讲者,将同时删除其论文。在 Paper 类中再次使用了 constraints 和 optionals。

现在已创建了域类,您将使用 Grails 的快速代码生成功能生成引用相应域类的各种代码文件,并为控制器、GUI 等生成代码。从本质上说,只需执行一个命令,即可为每个域类生成完整的创建/读取/更新/删除 (CRUD) 应用程序。您将为 generate-all 命令创建外部工具。此外部工具的参数如下:Program executable:${env:var=GRAILS_HOME}\bin\grails.bat Arguments:all ${promptl:label=Name} Run directory:${project.dir} 需要运行 generate-all 工具两次,每次提供一个域类作为参数。日志将显示 Grails 创建的所有文件和目录。现在可以针对 Speaker 和 Paper,试用这一具 CRUD 功能的 Grails 应用程序。我们先尝试运行此自动生成的应用程序,然后再对其进行自定义。只需运行 run-app 命令即可运行该应用程序。使用以下设置为 run-app 命令创建外部工具:Program executable:${env:var=GRAILS_HOME}\bin\grails.bat Arguments:run-app Run directory:${project.dir}Grails 附带一个内置的 Jetty 服务器,执行 run-app 命令时,将启动该服务器并在上面部署应用程序。虽然可在任何 Java EE 服务器上运行 Grails 应用程序,但开发期间在内置服务器上运行是最容易的一种方法。请在浏览器中访问 http://localhost:8080/Conference/,您会发现一个可以添加、编辑和删除演讲者和论文的 Web 应用程序。

数据源

在 grails-app/conf/DataSource.groovy 文件中可找到数据源配置。Grails 附带一个可使用此文件进行配置的内置 HSQL 数据库。请注意,在默认情况下,dbCreate 属性的值为“create-drop”。因此每次重新启动服务器时,都会删除旧数据库并创建新数据库。如果要保留旧值,请将该属性值更改为“update”。

要使用 HSQL 之外的数据库,请将该数据库的 JDBC 驱动程序添加到 lib 目录中,然后将连接字符串和驱动程序类名称添加到 DataSource.groovy 配置文件中。例如,要使用 Oracle 数据库 10g 快捷版作为生产数据库,需将 Oracle JDBC 瘦驱动程序添加到 lib 目录,然后按如下所示编辑 DataSource.groovy 文件:[code]production {

 dataSource {

    dbCreate = "update"

url = “jdbc:oracle:thin:@localhost:1521:XE”

driverClassName = “oracle.jdbc.OracleDriver”

   }

}[/code]Grails 的创建者提供了特别常见的应用程序开发要求:必须在开发、测试和生产数据库之间进行切换,因此在 DataSource.groovy 文件中存在多个数据源配置。通过将参数(dev、test、prod)传递给 run-app 命令,可以更改用于运行应用程序的数据库。默认值为“development”或“dev”。[code]grails run-app

grails dev run-app

grails prod run-app

grails test run-app
[/code]现在您有一个应用程序,可供会议组织者输入演讲者数据和论文数据,但是很显然,该应用程序目前还无法联机发布并由演讲者直接使用。

我们先来了解一下 Grails 的工作原理,然后再自定义该应用程序。

域、控制器和视图

Grails 的运行围绕着域、控制器和视图。我们来分析 Grails 中的一个工作流,以了解 Grails 的工作原理。在 http://localhost:8080/Conference 显示的页面有一个指向 http://localhost:8080/Conference/speaker/ 的链接。单击此链接将转至位于 http://localhost:8080/Conference/speaker/list 的演讲者列表页面。本例中涉及的步骤如下:

由于 Grails 具有特定惯例,因此不必通知它当 X 类型的请求进来时,必须使用 Y 控制器。因此,如果请求的形式为 /speaker/*,Grails 将自动在 /grails-app/controllers 目录中查找 SpeakerController。

SpeakerController 是运行 generate-all 命令时自动生成的类。此类为各种操作定义闭包。默认情况下定义为索引操作,索引的闭包为 def index = { redirect(action:list,params:params) }此闭包只将请求及其在请求中收到的参数重定向到列表操作。

列表操作如下所示:[code] def list = {

        if(!params.max) params.max = 10
                                    
        [ speakerList: Speaker.list( params ) ]

    }[/code]它将获取演讲者列表,并返回一个关键字为 speakerList 且值为 Speaker 对象列表的映射。

由于我们没有指出返回此映射后 Grails 应该执行什么操作,惯例再次发挥了作用。

因此,对于 SpeakerController 控制器中名为“list”的操作,Grails 将自动转至 /views/speaker 目录中的 list.gsp 视图并显示此视图。

list.gsp 每次使用 GSP 标记迭代 speakerList。

您将得到一个显示演讲者列表的页面。

我们已经了解了应用程序的工作原理,现在来修改演讲者注册和论文提交自定义应用程序的控制器和视图。

自定义布局

Grails 针对布局使用 SiteMesh。这些布局位于 grails-app/views/layouts 目录中。在我们前面查看的 list.gsp 视图中,您会注意到以下行<meta name="layout" content="main"></meta>sch此行通知 Grails 为此特定视图使用 main.gsp 中声明的布局。因此,如果您要修改该页面的布局,则需要编辑 main.gsp 文件。我们将徽标由 Grails 徽标更改为已放入 web-app/images/ 目录中的 OTN 徽标。<div class="logo"><img src="${createLinkTo(dir:'images',file:'otn_logo_small.gif')}" alt="OTN" /></div>通过修改 main.gsp 文件,可以很容易地添加标题和页脚、关联 CSS 文件,并对使用此布局的所有页面进行其他更改。

请注意,也可以不使用 main.gsp 方法,而使用惯例处理 GSP 布局。因此,如果您创建名为 grails-app/views/layouts/speaker.gsp 的布局,它将应用于 SpeakerController 委托给的所有视图。

还可以为单个操作创建布局,因此可在 grails-app/views/layouts/login/logout.gsp 中定义 LoginController 中注销操作的布局。