在1.2节中我们配置好了Grails框架的开发环境并且安装了必要的协助开发的工具,在这一节我们会结合示例项目,对Grails框架的各部分进行初步介绍。
Grails框架是基于配置的一个框架,可以根据每部分的名称、路径清晰且直观地了解各部分对应哪些功能。本章主要对Grails项目的初步建立进行介绍,已经对Grails框架各部分有过一些了解的读者可以跳过本章。
Grails框架提供了命令行界面(Command Line Interface,CLI),可以在CLI中通过简单的命令来创建、构建应用。在Linux操作系统下,我们可以打开终端,进入项目所在的目录,输入代码1.4中命令来创建应用。
# 进入项目所在目录 $ cd~/ grailsProjects # 创建名为intro的项目,该命令会在当前目录下创建以项目命名的目录 $ grails create -app intro | Application created at /home/User/grailsProjects/intro # 进入项目目录 $ cd intro # 查看自动创建出的目录和文件 $ ls -al
代码1.4 在命令行交互界面创建新的应用
在IDE中也可以通过菜单来创建Grails应用,如在IntelliJ IDEA中,可以在File- >New->Project下选择Grails框架,选择相应版本的Java SDK以及项目所在目录,根据提示继续操作即可创建应用。
由于第一次使用Grails框架创建应用时很多依赖包还未下载到本地,需要访问一些插件网站,耐心等待即可。依赖包下载完成、创建命令运行结束后,我们的第一个项目便创建完成。
项目创建完成后,在项目目录下可以在终端通过tree -d ~/grailsProjects/intro命令来查看项目目录结构,代码1.5对每个目录的结构进行了说明,读者可以对照查看。
# 查看项目目录结构 $ tree -d~/ grailsProjects/intro /home/User/grailsProjects/intro gradle # Grails3使用Gradle进行构建,可通过Gradle导入 wrapper grails -app assets # 静态文件,如CSS、JavaScript、Images等 images javascripts stylesheets conf # 项目运行需要的配置文件,使用YAML文件或Groovy 文件进行配置 spring controllers # 相当于MVC架构中的Controller,用来发起和处理 HTTP请求,文件以“Controller”结尾,如“Example Controller.groovy” intro domain # 模型,通过GORM与数据库对应 i18n # 国际化相关文件 init # Bootstrap和Main 引导程序,主应用程序文件,可以使用默认设置运行程序 intro services # 服务层,实现应用的核心业务逻辑,提高重用性,更好地实现问题分离,文件以“Service”结尾,如“ExampleService.groovy” taglib # 显示效果定制,作为GSP文件中可引用的类库 utils # 特定的应用代码 views # GSP文件,用于显示,相当于MVC中的View layouts src integration -test # 集成测试 groovy resources main # 其他测试文件 groovy webapp test # 单元测试 groovy
代码1.5 项目目录结构
Grails框架遵循“约定优于配置”的软件设计原则,项目中的每部分都是依据约定的形式存在的,省去了很多显式配置的过程,减少了开发者的配置工作,大幅提升了开发效率。基本的约定诸如grails-app/domain/目录下为领域类模型;grails-app/controllers/目录下以Controller结尾的文件为模型对应的控制器;grails-app/views/目录下为每个模型对应的视图,子目录名称与模型名称相同。在这样的设计模式下,通过文件所在的位置以及文件的名称就可以知道文件的用途。因此我们也有必要熟悉Grails框架的目录结构。
项目中其他主要文件如下。
· build.gradle: 项目的配置文件,包括使用到的所有的插件、依赖以及构建相关的内容。
· gradle.properties: 定义在build.gradle中可以使用的变量。
· grailsw: Grails框架打包工具,可以在未安装Grails环境的情况下使用。
· gradlew: Gradle打包工具,可以在未安装Gradle的情况下使用。
控制器,即框架中的Controller,是处理用户端与服务端交互的组件。这里我们以创建控制器为开端进行示例项目的开发。
可以通过命令行交互界面创建控制器,如代码1.6所示,首先我们进入项目所在目录,然后通过create-controller命令创建一个控制器。
# 进入项目所在目录 $ cd~/ grailsProjects/intro # 创建名为hello的控制器 # 自动创建出HelloController.groovy和测试文件HelloControllerSpec.groovy $ grails create -controller hello | Created grails -app/controllers/intro/HelloController.groovy | Created src/test/groovy/intro/HelloControllerSpec.groovy
代码1.6 创建HelloController
在文件HelloController.groovy中,我们按照代码1.7进行更改。
package intro class HelloController { def index() { render 'Hello World!' } }
代码1.7 编写HelloController代码
在这个例子中,我们使用render()方法将字符串“Hello World!”输出到界面。通过执行grails run-app命令,我们可以在本地8080端口启动该项目,然后访问http://localhost:8080查看效果,如图1.3所示。
图1.3 示例项目启动界面(HelloController)
我们可以直接单击页面中的intro.HelloController链接来访问HelloController下的in dex()方法,也可以直接访问链接http://localhost:8080/hello/index,进入页面后可以看到页面显示出“Hello World!”。
模型,即框架中的Domain,它反映数据库结构与字段设置,是软件的业务概念模型,在使用时需要安装和配置数据库。数据库的配置在grails-app/conf/application.yml文件中的dataSource节点下。新创建项目的数据源默认使用H2数据库,可以通过更改相关配置切换到MySQL或者其他类型数据库。此处我们使用默认配置。
配置好数据库后便可以开始创建模型。在任何一个应用系统中,数据模型都是最基本的构成,是对业务的描述和表达,创建模型也是项目搭建过程中需要首先完成的工作。代码1.8为通过命令行创建Person模型。
# 进入项目所在目录 $ cd~/ grailsProjects/intro # 创建名为Person的Domain类 # 自动创建出Person.groovy和测试文件PersonSpec.groovy $ grails create -domain -class Person | Created grails -app/domain/intro/Person.groovy | Created src/test/groovy/intro/PersonSpec.groovy
代码1.8 创建Person模型
我们创建了一个Person模型,或者说创建了一个名称为Person的数据表,Person模型中的属性即Person数据表的属性字段。在这个类中,我们添加firstName、lastName等人员属性,更改Person.groovy文件,如代码1.9所示。
package intro class Person { String firstName // 名字 String lastName // 姓氏 String gender // 性别 Integer age // 年龄 Boolean active = false // 设置默认值为false static constraints = { firstName nullable: true , maxSize : 32 lastName nullable: true , maxSize : 32 gender nullable: true , inList: ['male', 'female'] age nullable: true active nullable: true } }
代码1.9 编写Person模型
在添加的内容中,对每个属性做了一些约束的设置,比如设置默认值是否为空(nullable),字段大小(maxSize)以及字段值(inList)的选择。我们在添加属性的时候应该尽量避免使用基本数据类型(int、boolean等),而应该优先使用封装的数据类型(Integer、Boolean等)。
Domain类的定义过程和Java框架相比,省去了很多重复性的工作,比如定义getting()和setting()方法,以及拆箱和装箱操作。运行过程中Groovy会根据使用情况来判断并完成这些基础操作。
模型创建完成后启动项目,可以通过访问http://localhost:8080/dbconsole来查看数据库的内容。其中在JDBC URL处填写的内容与conf/application.yml文件中的development.dataSource配置保持一致,默认为jdbc:h2:mem:devDb;MVCC=TRUE。
进入数据库控制台后可以在左侧看到新创建的Person表,以及我们设置的每个字段,也可通过grails schema-export命令导出数据库结构。
在Domain文件中,我们可以为每个字段添加约束条件,如代码1.9中闭包constraints所示。约束条件为数据持久化过程校验规则,常见的约束条件有email、url、max、min等,想了解更多约束条件可以查看官方文档。同时我们也可以用validator的形式来创建自定义约束条件,对数据字段进行特定的限制。
Grails提供grails console命令对项目进行快速调试。项目启动后,在项目目录下调用grails console命令打开运行时控制台,如代码1.10所示。在控制台窗口中可以运行Groovy代码来进行调试。
# 进入项目所在目录 $ cd~/ grailsProjects/intro # 运行grails console命令 $ grails console Using grails version 3.3.5 in this shell. | Running console...
代码1.10 开启grails console控制台
在grails console交互界面,可以使用代码1.11中的操作测试约束条件的效果。调用save()方法保存数据时进行规则校验,验证的结果会以列表的形式返回,后面章节会对错误处理进行详细介绍。
import intro.* def person = new Person() person.gender = 'man' // 可以调用validate()方法进行约束的主动验证 // 在调用save()方法持久化到数据库时,会自动调用validate()方法进行验证 println person.validate() // false,验证未通过,因为'man'不在['male','female']中 person.gender = 'male' println person.validate() // true,验证通过
代码1.11 在grails console中进行约束条件测试
我们可以在Domain类中添加自定义的方法进行定制,比如编写toString()方法,覆盖默认的toString()实现,其他的类方法也可以进行定制实现,如代码1.12所示。需要注意Grails框架不会动态加载Domain的更改,因为涉及对应数据库的更新,所以修改后需重新启动项目才能生效。
String toString() { firstName + " " + lastName // 方法的最后一句执行结果即为该方法的返回值 // return firstName + " " + lastName // 与上句等同效果 }
代码1.12 在Domain中定义方法
Scafolding,在中文中称为脚手架。在大多数项目中,我们对数据的操作通常都是类似的,比如添加、读取、写入、删除数据等。脚手架的功能则是将这些类似的操作抽象出来,以模板的形式提供功能,无须每次编写相同功能的代码,节省开发时间。在Grails框架中,脚手架可以根据模板文件为每个Domain类生成统一的增、删、改、查操作,同时生成统一的显示页面。应用目录下的build.gradle文件中引入了脚手架插件:compile''org.grails.plugins:scafolding''。引用后便可以使用脚手架特性。在/.gradle/caches/modules-2/files-2.1/org.grails.plugins/scafolding/目录下可以查看该插件的代码部分,插件包中集成了常用的模板,比如Con troller以及显示界面(show.gsp)。
脚手架使用分为两种形式,一种是动态的,一种是静态的。
动态脚手架使用很简单,只需要在创建的Controller中指定Domain类。我们通过grails create-controller Test来创建一个新的Controller,但是在创建Controller时会同步在grails app/views/下创建test目录,为了使用脚手架,我们需要将该目录手动删除,同时更改该Controller的内容,如代码1.13所示。
package intro class TestController { static scaffold = Person }
代码1.13 动态脚手架
启动项目后访问http://localhost:8080/即可看到intro.TestController链接,单击即访问了TestController的index()方法。在没有编写对应功能代码的前提下,仅靠脚手架便实现了基本功能。我们还可以在这个界面尝试创建Person记录。脚手架插件默认对in dex()、list()、show()、edit()、delete()、create()、save()、update()等基本数据处理方法进行了包装。
静态脚手架,即将模板代码在生成Controller时同步添加过来。通过grails generate controller Person创建的Controller默认使用静态脚手架。执行完命令后打开PersonCon troller.groovy文件可以看到自动写入的代码片段。我们再通过grails generate-views Person来生成页面,可以在grails-app/views/person目录下查看相应的页面代码。
生成页面后,我们重启项目,访问http://localhost:8080/即可看到相应效果。
我们可以看到,单击intro.TestController和intro.PersonController进入的界面都是一样的。动态和静态只是两种实现方法,使用的是同一套模板(在不添加模板文件的情况下),区别在于后继的定制化是否便捷。
至此我们就可以在开发过程中运行项目进行访问测试了。