一,搭建Grails环境
0,下载Grails( http://dist.codehaus.org/grails/grails-bin-1.0.zip,请留意朝花夕拾——Groovy & Grails中的“最新版本”提示)并解压到自己指定位置(我的位置是D:/D/MY_DEV/grails)
1,设置环境变量GRAILS_HOME(注意大写),过程与“设置环境变量GROOVY_HOME”相似
2,将%GRAILS_HOME%/bin添加到环境变量path中,过程与“将GROOVY_HOME目录下的bin追加到环境变量path中”相似
(如果只想进行Grails开发,可以不设GROOVY_HOME)
二,创建Grails Demo程序
3,打开“命令行”,选择当前目录(我的为D:/Temp/grails_apps),在黑底白字的窗口中输入“grails create-app demo”,不包括双引号“”,在您的屏幕中可以看到类似下面的输出结果:
D:/_DEV/grails_apps>grails create-app demo
Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:/D/MY_DEV/grails-1.0
Base Directory: D:/_DEV/grails_apps
Environment set to development
Note: No plugin scripts found
Running script D:/D/MY_DEV/grails-1.0/scripts/CreateApp.groovy
[mkdir] Created dir: D:/_DEV/grails_apps/demo/src
[mkdir] Created dir: D:/_DEV/grails_apps/demo/src/java
[mkdir] Created dir: D:/_DEV/grails_apps/demo/src/groovy
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/controllers
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/services
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/domain
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/taglib
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/utils
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/views
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/views/layouts
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/i18n
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/conf
[mkdir] Created dir: D:/_DEV/grails_apps/demo/test
[mkdir] Created dir: D:/_DEV/grails_apps/demo/test/unit
[mkdir] Created dir: D:/_DEV/grails_apps/demo/test/integration
[mkdir] Created dir: D:/_DEV/grails_apps/demo/scripts
[mkdir] Created dir: D:/_DEV/grails_apps/demo/web-app
[mkdir] Created dir: D:/_DEV/grails_apps/demo/web-app/js
[mkdir] Created dir: D:/_DEV/grails_apps/demo/web-app/css
[mkdir] Created dir: D:/_DEV/grails_apps/demo/web-app/images
[mkdir] Created dir: D:/_DEV/grails_apps/demo/web-app/WEB-INF/classes
[mkdir] Created dir: D:/_DEV/grails_apps/demo/web-app/META-INF
[mkdir] Created dir: D:/_DEV/grails_apps/demo/lib
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/conf/spring
[mkdir] Created dir: D:/_DEV/grails_apps/demo/grails-app/conf/hibernate
[propertyfile] Creating new property file: D:/_DEV/grails_apps/demo/application.properties
[copy] Copying 2 files to D:/_DEV/grails_apps/demo
[copy] Copying 2 files to D:/_DEV/grails_apps/demo/web-app/WEB-INF
[copy] Copying 5 files to D:/_DEV/grails_apps/demo/web-app/WEB-INF/tld
[copy] Copying 87 files to D:/_DEV/grails_apps/demo/web-app
[copy] Copying 17 files to D:/_DEV/grails_apps/demo/grails-app
[copy] Copying 1 file to D:/_DEV/grails_apps/demo
[copy] Copying 1 file to D:/_DEV/grails_apps/demo
[copy] Copying 1 file to D:/_DEV/grails_apps/demo
[propertyfile] Updating property file: D:/_DEV/grails_apps/demo/application.properties
Created Grails Application at D:/_DEV/grails_apps/demo
D:/_DEV/grails_apps>
通过“grails create-app”这个命令,Grails自动帮我们创建了开发所需的工程环境。其实您现在就已经拥有了一个可运行的Web应用程序,
然后进入demo目录(“cd demo”),输入“grails run-app”,回车,启动这个‘五脏俱全’的程序雏形,打开浏览器,输入 http://localhost:8080/demo ,回车,看到了吧 :) 让我们继续吧,请停止这个程序(Ctrl + C)
4,在“命令行”中输入“cd demo”
,回车,
以进入demo目录,
然后再输入“grails create-domain-class User”创建domain class即类似于pojo的pogo,它对应MVC中的Model,不过由Grails自动创建的pogo是空的,需要自己添加属性,约束(constraints)等。输出结果如下所示:
D:/_DEV/grails_apps/demo>grails create-domain-class User
Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:/D/MY_DEV/grails-1.0
Base Directory: D:/_DEV/grails_apps/demo
Environment set to development
Note: No plugin scripts found
Running script D:/D/MY_DEV/grails-1.0/scripts/CreateDomainClass.groovy
[copy] Copying 1 file to D:/_DEV/grails_apps/demo/grails-app/domain
Created for User
[copy] Copying 1 file to D:/_DEV/grails_apps/demo/test/integration
Created Tests for User
D:/_DEV/grails_apps/demo>
5,进入D:/Temp/grails_apps/demo/grails-app/domain(这个目录中存放着所有的domain class),打开User.groovy,修改为如下内容:
class
User {
String name
String password
String toString() {
"
$name : $password
"
}
static
constraints
=
{
name(blank:
false
)
password(blank:
false
, size:
6
..
16
)
}
}
contraints这个类变量是定义一些约束的,比如name不能为空白,password不能为空白而且长度在6到16之间(包括6和16)
6,在“命令行”中输入“grails generate-all User”,为User产生所有CRUD操作需要的代码(如控制器UserController.groovy)和页面(如list.gsp),输出结果如下所示:
D:/_DEV/grails_apps/demo>grails generate-all User
Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:/D/MY_DEV/grails-1.0
Base Directory: D:/_DEV/grails_apps/demo
Environment set to development
Note: No plugin scripts found
Running script D:/D/MY_DEV/grails-1.0/scripts/GenerateAll.groovy
[mkdir] Created dir: D:/_DEV/grails_apps/demo/web-app/WEB-INF/lib
[mkdir] Created dir: C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/classes
[groovyc] Compiling 7 source files to C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/classes
[mkdir] Created dir: C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/resources/grails-app/i18n
[native2ascii] Converting 10 files from D:/_DEV/grails_apps/demo/grails-app/i18n to C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/re
sources/grails-app/i18n
[copy] Copying 1 file to C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/classes
[copy] Copying 1 file to C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/resources
[copy] Copying 1 file to C:/Documents and Settings/Daniel/.grails/1.0/projects/demo
[0] spring.GrailsWebApplicationContext Refreshing org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@2b2057: display name [org
.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@2b2057]; startup date [Tue Feb 05 23:26:45 CST 2008]; root of context hierarch
y
[16] spring.GrailsWebApplicationContext Bean factory for application context [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationConte
xt@2b2057]: org.springframework.beans.factory.support.DefaultListableBeanFactory@eebf17
Generating views for domain class User ...
Generating controller for domain class User ...
Finished generation for domain class User
D:/_DEV/grails_apps/demo>
7,修改demo/grails-app/controllers/UserController.groovy的内容为:
class
UserController {
def loginService
//
新增的代码
def index
=
{ redirect(action:list,params:params) }
//
the delete, save and update actions only accept POST requests
def allowedMethods
=
[delete:
'
POST
'
, save:
'
POST
'
, update:
'
POST
'
]
def list
=
{
if
(
!
params.max) params.max
=
10
[ userList: User.list( params ) ]
}
def show
=
{
def user
=
User.get( params.id )
if
(
!
user) {
flash.message
=
"
User not found with id ${params.id}
"
redirect(action:list)
}
else
{
return
[ user : user ] }
}
def delete
=
{
def user
=
User.get( params.id )
if
(user) {
user.delete()
flash.message
=
"
User ${params.id} deleted
"
redirect(action:list)
}
else
{
flash.message
=
"
User not found with id ${params.id}
"
redirect(action:list)
}
}
def edit
=
{
def user
=
User.get( params.id )
if
(
!
user) {
flash.message
=
"
User not found with id ${params.id}
"
redirect(action:list)
}
else
{
return
[ user : user ]
}
}
def update
=
{
def user
=
User.get( params.id )
if
(user) {
user.properties
=
params
if
(
!
user.hasErrors()
&&
user.save()) {
flash.message
=
"
User ${params.id} updated
"
redirect(action:show,id:user.id)
}
else
{
render(view:
'
edit
'
,model:[user:user])
}
}
else
{
flash.message
=
"
User not found with id ${params.id}
"
redirect(action:edit,id:params.id)
}
}
def create
=
{
def user
=
new
User()
user.properties
=
params
return
[
'
user
'
:user]
}
def save
=
{
def user
=
new
User(params)
if
(
!
user.hasErrors()
&&
user.save()) {
flash.message
=
"
User ${user.id} created
"
redirect(action:show,id:user.id)
}
else
{
render(view:
'
create
'
,model:[user:user])
}
}
//
新增的代码
def login
=
{
if
(request.method
==
'
POST
'
) {
User u
=
new
User()
u.properties
=
params
if
(
!
u.validate()) {
render(view:
'
login
'
, model:[user:u])
}
if
(params.name
&&
params.password) {
def user
=
loginService.check(u)
if
(user) {
flash.message
=
"
Welcome ${user.name}
"
render(view:
"
ok
"
, model: [user: user])
}
else
{
flash.error
=
"
Invalid ${u.name} with ${u.password}
"
render(view:
"
login
"
, model: [user: u])
}
}
else
{
render(view:
"
login
"
, model: [user: u])
}
}
}
}
大家或许也看到了LoginService这个类,我将在后面演示创建它,这个LoginService类封装了所有登陆相关的业务逻辑,Grails会自动将其注入到UserController中
8,在“命令行”中,输入“grails create-service Login”,创建LoginService.groovy,输出:
D:/_DEV/grails_apps/demo>grails create-service Login
Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:/D/MY_DEV/grails-1.0
Base Directory: D:/_DEV/grails_apps/demo
Environment set to development
Note: No plugin scripts found
Running script D:/D/MY_DEV/grails-1.0/scripts/CreateService.groovy
[copy] Copying 1 file to D:/_DEV/grails_apps/demo/grails-app/services
Created Service for Login
[copy] Copying 1 file to D:/_DEV/grails_apps/demo/test/integration
Created ServiceTests for Login
D:/_DEV/grails_apps/demo>
9,修改demo/grails-app/services/LoginService.groovy的内容为:
class
LoginService {
boolean
transactional
=
true
def check(User u) {
def user
=
User.findWhere(name: u.name, password: u.password)
return
user
}
}
10,在demo/grails-app/views/user目录下创建login.gsp和ok.gsp,它们对应MVC中的View,内容分别为:
login.gsp (复制demo/grails-app/views/user/create.gsp的内容到login.gsp中,并修改):
<
html
>
<
head
>
<
meta
http-equiv
="Content-Type"
content
="text/html; charset=UTF-8"
/>
<
meta
name
="layout"
content
="main"
/>
<
title
>
Login
title
>
head
>
<
body
>
<
div
class
="nav"
>
<
span
class
="menuButton"
><
a
class
="home"
href
="${createLinkTo(dir:'')}"
>
Home
a
>
span
>
<
span
class
="menuButton"
><
g:link
class
="list"
action
="list"
>
User List
g:link
>
span
>
div
>
<
div
class
="body"
>
<
h1
>
Login
h1
>
<
g:if
test
="${flash.error}"
>
<
div
class
="errors"
>
${flash.error}
div
>
g:if
>
<
g:hasErrors
bean
="${user}"
>
<
div
class
="errors"
>
<
g:renderErrors
bean
="${user}"
as
="list"
/>
div
>
g:hasErrors
>
<
g:form
action
="login"
method
="post"
>
<
div
class
="dialog"
>
<
table
>
<
tbody
>
<
tr
class
="prop"
>
<
td
valign
="top"
class
="name"
>
<
label
for
="name"
>
Name:
label
>
td
>
<
td
valign
="top"
class
="value ${hasErrors(bean:user,field:'name','errors')}"
>
<
input
type
="text"
id
="name"
name
="name"
value
="${fieldValue(bean:user,field:'name')}"
/>
td
>
tr
>
<
tr
class
="prop"
>
<
td
valign
="top"
class
="name"
>
<
label
for
="password"
>
Password:
label
>
td
>
<
td
valign
="top"
class
="value ${hasErrors(bean:user,field:'password','errors')}"
>
<
input
type
="text"
maxlength
="16"
id
="password"
name
="password"
value
="${fieldValue(bean:user,field:'password')}"
/>
td
>
tr
>
tbody
>
table
>
div
>
<
div
class
="buttons"
>
<
span
class
="button"
><
input
class
="save"
type
="submit"
value
="Login"
/>
span
>
div
>
g:form
>
div
>
body
>
html
>
ok.gsp:
<
g:if
test
="${flash.message}"
>
<
div
class
="message"
>
${flash.message}
div
>
g:if
>
Name: ${user?.name}
<
br
>
Password: ${user?.password}
11,修改demo/grails-app/conf/BootStrap.groovy,初始化数据库:将一个User实例保存到数据库(grails自带hsqldb和jetty)中,内容如下:
class
BootStrap {
def init
=
{ servletContext
->
new
User(name:
"
demo
"
, password:
"
123456
"
).save()
}
def destroy
=
{
}
}
12,在“命令行”中,输入“grails run-app”,运行我们的Web应用,输出如下:
D:/_DEV/grails_apps/demo>grails run-app
Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:/D/MY_DEV/grails-1.0
Base Directory: D:/_DEV/grails_apps/demo
Environment set to development
Note: No plugin scripts found
Running script D:/D/MY_DEV/grails-1.0/scripts/RunApp.groovy
[groovyc] Compiling 4 source files to C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/classes
Running Grails application..
2008-02-05 23:46:08.912::INFO: Logging to STDERR via org.mortbay.log.StdErrLog
2008-02-05 23:46:08.066::INFO: jetty-6.1.4
2008-02-05 23:46:08.347::INFO: No Transaction manager found - if your webapp requires one, please configure one.
2008-02-05 23:46:09.081:/demo:INFO: Set web app root system property: 'demo' = [D:/_DEV/grails_apps/demo/web-app/]
2008-02-05 23:46:09.081:/demo:INFO: Initializing Log4J from [file:C:/Documents and Settings/Daniel/.grails/1.0/projects/demo/resources/log4j.pro
perties]
2008-02-05 23:46:09.113:/demo:INFO: Initializing Spring root WebApplicationContext
[0] spring.GrailsWebApplicationContext Refreshing org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@5facbd: display name [org
.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@5facbd]; startup date [Tue Feb 05 23:46:14 CST 2008]; parent: org.springframew
ork.web.context.support.XmlWebApplicationContext@1fef80a
[0] spring.GrailsWebApplicationContext Bean factory for application context [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContex
t@5facbd]: org.springframework.beans.factory.support.DefaultListableBeanFactory@aa4c7c
2008-02-05 23:46:21.590:/demo:INFO: Initializing Spring FrameworkServlet 'grails'
2008-02-05 23:46:21.871::INFO: Started [email protected]:8080
Server running. Browse to http://localhost:8080/demo
13,打开浏览器,输入:http://localhost:8080/demo/user/login ,在Name处输入demo,Password处输入123456,点击‘Login’,跳转到成功页面:
Welcome demo
Name: demo
Password: 123456
如果您对Grails的工程目录不太熟悉,我这里为大家提供了一张表,详细地描述了各目录的用途:
《Grails权威指南》
表
3-1.
Grails
工程目录
目录名称
|
相关描述
|
grails-app
|
此目录包含了
Grails
应用程序的核心工件
(core artifact)
|
+ conf
|
此目录包含了诸如
DevelopmentDataSource.groovy
的配置文件
|
+ controllers
|
此目录包含了处理请求
(request)
的控制器
(controller)
,
Grails
控制器将在第
7
章中进行讲解
|
+ domain
|
此目录包含了领域模型
(
domain model
)
,领域模型将在第
4
章进行讲解
|
+ i18n
|
此目录包含了用于国际化的消息束
(message bundle)
(译者注:指的是
properties
文件,如
messages.properties
)
|
+ services
|
此目录包含了封装业务逻辑的
service
文件,
service
将在第
10
章中进行讲解
|
+ taglib
|
此目录包含了辅助页面生成的动态标签库,动态标签将在第
8
章中进行讲解
|
+ views
|
此目录包含了
Groovy
服务器页面
(GSP)
以及
JSP
页面
|
+ layouts
|
此目录包含了
GSP
或
JSP
的布局
(layout)
,这些布局由
SiteMesh
提供支持,这将在第
8
章中进行讲解
|
grails-test
|
此目录包含了应用程序的单元测试
|
hibernate
|
此目录包含了可选的Hibernate配置文件,这将在第11章中进行讲解
|
lib
|
此目录包含了
jar
文件
|
spring
|
此目录包含了可选的Spring配置文件,这将在第11章中进行讲解
|
src
|
此目录包含了其他
Groovy
和
Java
资源
|
+ java
|
此目录包含了待编译的
Java
源文件
|
+ groovy
|
此目录包含了待编译的
Groovy
源文件
|
web-app
|
此目录包含了
Web
应用程序的资源(
CSS
,
JavaScript
等)
|
注:Grails1.0已将hibernate和spring两个目录移到grails-app/conf目录下了,
而grails-test目录也更名为test,test目录下有integration目录和unit目录,分别存放集成测试代码和单元测试代码
想象一下用您平时做项目时所用的框架组合(比如SSH)来创建同样的Web应用程序,您立刻会感受,Grails让我们专注于业务逻辑,而不用浪费时间在那些scaffolding code(如配置文件)上。从今天开始,您不用再羡慕那些Ruby程序员所用的RoR了,您大可以使用Grails来高效开发Web应用。
您也可以访问Grails官方网站(http://www.grails.org)进一步学习。