还剩68页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
TOC\o1-3\h\z\uGroovy轻松入门——搭建Groovy__环境1Groovy轻松入门——通过与J__a的比较,迅速掌握Groovy(更新于
2007.
09.23)3Groovy轻松入门——Grails实战之遗留框架利用篇53Groovy轻松入门——搭建Groovy__环境http://___.blogj__a.net/BlueSUN/archive/2007/03/17/
104391.html既然是入门,我先不介绍那些IDE的东西,比如Eclipse中的Groovy插件(如果您迫不及待的话,可以先看一下__Groovy的Eclipse插件http://___.blogj__a.net/BlueSUN/archive/2007/04/02/
107858.html),我先讲一下如何设置Groovy的环境变量我目前所用的系统是WindowsXP,最后运行一个Helloworld程序告终Groovy既然是J__a帝国的王储http://___.blogj__a.net/BlueSUN/archive/2007/03/03/
101562.html,当然少不了J__a的支持0,先__JDK(推荐版本为
1.5及
1.5以上,当然
1.4也可以)然后设置J__a的环境变量1,设置环境变量j__a_home(设置环境变量XXX_home的一个好处是只要修改XXX_home的值,与之相关的%XXX_home%\bin等的值都相应改变,这样就能做到‘一处修改,处处修改’)右击‘我的电脑’- ‘属性’-‘高级’-‘环境变量’-__‘新建’(用户变量与系统变量均可,挑一便是)-输入‘变量名’为j__a_home-输入‘变量值’为JDK的所在目录(默认__位置为C:\ProgramFiles\J__a\jdk
1.
6.0,我装的是JDK
6.0)-__‘确定’-环境变量j__a_home设置成功2,设置环境变量path环境变量j__a_home设置好之后,我们开始设置环境变量path前面的步骤与‘设置环境变量j__a_home’相同,到__‘新建’按钮时,选择新建用户变量(因为系统变量path已经存在,如果追加在长串已存在的path值后面,比较凌乱)-输入‘变量名’为path-输入‘变量值’为“%j__a_home%\bin;”不包括双引号“”3,设置环境变量classpath环境变量path设置好之后,我们开始设置环境变量classpath前面的步骤与‘设置环境变量j__a_home’相同,到__‘新建’按钮时,选择新建系统变量(我的个人习惯,你也可以选择新建用户变量)-输入‘变量名’为classpath-输入‘变量值’为“.;%j__a_home%\lib;”不包括双引号“”,注意不要漏了最前面的小圆点.如果你已经__了JDK,并设置好了J__a环境变量,请跳过上述过程,直接__GDK(只需3步)(如果您下载的是Groovy__版DownloadWindows-Installer:BinaryReleasehttp://groovy.codehaus.org/Download,请将__过程中出现的选项都打上勾,以下4,5,6步骤可以跳过)请留意朝花夕拾——GroovyGrailshttp://___.blogj__a.net/BlueSUN/archive/2007/03/archive/2007/04/23/
112978.html中的Groovy最新稳定版的版本号4,下载GDKhttp://dist.codehaus.org/groovy/distributions/groovy-
1.
0.ziphttp://dist.codehaus.org/groovy/distributions/groovy-
1.
0.zip并将下载的groovy-
1.
0.zip文件解压到指定位置(我的位置是D:\D\MY_DEV\groovy),5,设置环境变量GROOVY_HOME步骤与“设置环境变量j__a_home”类似,到输入‘变量名’时,输入‘GROOVY_HOME’-输入‘变量值’为你解压指定位置(我的变量值为D:\D\MY_DEV\groovy),需要注意一点,解压目录如D:\D\MY_DEV\groovy中不可有空格,比如D:\D\MY DEV\groovy6,将GROOVY_HOME目录下的bin追加到环境变量path中步骤与“设置环境变量path”类似,找到你设置的path,然后将“%GROOVY_HOME%\bin”追加到path值(按上述过程,你现在的path为“%j__a_home%\bin;”)之后,你的path值为“%j__a_home%\bin;%GROOVY_HOME%\bin”,注意用英文分号;分开,不要有空白字符如空格,Tab等最后,我想提醒大家的是,不要将GROOVY_HOME目录下的jar包(比如GROOVY_HOME\embeddable\groovy-all-
1.
0.jar)添加到环境变量classpath中,因为Groovy自己会将GROOVY_HOME\lib下的所有jar文件(其中包括了Groovy相关的jar文件,如groovy-
1.
0.jar)添加到Groovy的classpath中,而groovy同样会用J__a的classpath(系统变量中的classpath),如果将Groovy相关jar文件如groovy-all-
1.
0.jar添加到环境变量classpath中,jar文件会产生冲突,今后的Groovy生活(如利用Grails方便快捷地__Web应用)就将成为泡影:好了,现在请大家打开Windows下的dos,即‘命令行’,在那个黑底白字的窗口中输入“groovyConsole”,回车,过一会儿就会出现一个GroovyConsole的窗口,在上面的文本域中,输入println Hello world! // 打印Hello world!然后按Ctrl+R来运行你的第一个Helloworld程序,在下面的窗口中便可看到运行结果Helloworld!祝贺你,第一个Groovy程序运行成功!Groovy轻松入门——通过与J__a的比较,迅速掌握Groovyhttp://___.blogj__a.net/BlueSUN/archive/2007/03/10/
103014.html在前几篇文章中,我已经向大家介绍了Groovy是什么,学习Groovy的重要性等内容,还不了解Groovy的朋友不妨去看看我Blog中的Groovy分类http://___.blogj__a.net/BlueSUN/category/
18316.html下面我将通过Groovy与J__a的比较,解开Groovy的神秘面纱ReadyStart!注意本教程是针对Groovy最新版本编写的Groovy和J__a的相同点有3+4+6+8+10+12+13141518+20+21222328+29+30+31+32++表示Groovy不但涵盖了J__a的语法,而且还有增强部分Groovy和J__a的不同点有0125791116171924252627 下面所列序号不分先后顺序
0.在Groovy可以用def定义无类型的变量定义变量方面def与J__aScript中的var相似,和返回值为无类型的方法,而在J__a中没有defGroovy:class __n { def name = 山风小子 def introdu__ { return Im $name // return可以省略 }}
1.J__a中的equals方法对应Groovy中的==而J__a中的==(判断是否引用同一对象)对应Groovy中的is方法eg.Test
1.j__a:public class Test { public static void __inString[] args { String name1 = 山风小子; String name2 = new String山风小子; // Groovy中写为 name1 == name2 if name
1.equalsname2 { System.out.printlnequal; } else { System.out.printlnnot equal; } // Groovy中写为 name
1.isname2 if name1 == name2 { System.out.printlnidentical; } else { System.out.printlnnot identical; } }与Test
1.j__a相对应的Test
1.groovy:String name1 = 山风小子 // 你也可以这样写 def name1 = 山风小子 其中的def可以理解为J__aScript中定义变量的varString name2 = new String山风小子 //请注意Groovy的句尾的分号时可选的,即可要可不要,前提是一行代码一条语句// J__a中写为 name
1.equalsname2if name1 == name2 { System.out.printlnequal;} else { System.out.printlnnot equal; }// J__a中写为 name1 == name2if name
1.isname2 { System.out.printlnidentical;} else { System.out.printlnnot identical; }
2.J__a中的数组定义int[]a={123};在Groovy写成int[]a=
[123]
3.J__a中的for循环forinti=0;ilen;i++{...}在Groovy中还可以写成foriin
0..len-1{...}或者foriin
0..len{...}//groovy
1.5也支持for;;J__a:for int i =0; i len; i++ { // do something}Groovy:for int i =0; i len; i++ { // do something}// 或者for i in
0..len-1 { // do something}// 或者for i in
0..len { // do something}
4.J__a中的方法返回写为return;或者returno__;在Groovy的方法中return是可选的J__a:public String sayHello { return Hello 山风小子;}Groovy:public String sayHello { return Hello 山风小子}//或者public String sayHello { Hello 山风小子}//或者String sayHello { Hello 山风小子}//或者public sayHello { Hello 山风小子}// 或者def sayHello { Hello 山风小子}
5.J__a中的innerclass即内部类,在Groovy中用Closure实现(Closure是J__a7正在考虑的一个特性,比innerclass在语义方面更完善)
6.Groovy中的注释比J__a多了首行注释#!,其他与J__a相同比如单行注释// 多行注释/* */ 或者是 支持j__adoc的/** */J__a:/* * 多行注释 *//** * j__adoc 注释 */// 单行注释Groovy:#!首行注释,使Unixshell能够定位Groovy启动程序以运行Groovy代码,例如#!/usr/bin/groovy/* * 多行注释 *//** * j__adoc 注释 */// 单行注释
7.J__a5中的for-each forTypet:iteratable{...} 在Groovy中,fortiniteratable{...}J__a:for Type t : iterable { // do something}Groovy:for t in iterable { // do something}
8.Groovy中switch语句与J__a中相同,不过支持更多类型了,比如String
9.Groovy的while语句跟J__a相同,但废弃了do-while(考虑到语义方面的问题,而且do-while可以用其他形式的循环语句代替,使用频率低)
10.J__a中的String常量表示为Hello山风小子,在Groovy中可如下表示// 双引号Hello 山风小子// 单引号也可以Hello 山风小子//多行字符串Hello山风小子//或者Hello山风小子// 替代字符串def name = 山风小子Hello ${name}//或者Hello $name
11.在Groovy中定义类,定义方法与J__a中定义类相同,唯一区别在于Groovy中类,属性以及方法默认都是public的,而在J__a中默认是package的,另外,在Groovy中可以用def来定义方法,请看注释J__a:public class Hello { private String name = 山风小子; public void sayHello { System.out.printlnHello + name; }}Groovy:class Hello { private String name = 山风小子 public void sayHello { //println与J__a中System.out.println相同 println Hello $name } /* sayHello也可以这样定义 def sayHello { println Hello $name } */}
12.对象创建在J__a写为Thoughtt=newThought;在Groovy也可以这样写,不过还多了种写法deft=newThought;
13.静态方法调用在J__a和Groovy中相同,即ClassName.staticMethodName;
14.实现接口和继承父类方面Groovy也与J__a完全相同,即实现接口classClassNameimplementsInte_____Name{...} 继承父类classClassNameextendsSuperClass{...}
15.定义接口方面Groovy与J__a完全相同,即inte_____Inte_____Name{...} //在Groovy中默认为public的
16.正则表达式常量在J__a中没有,在Groovy中表示为/pattern/
17.Hash常量类型为j__a.util.Hash__p在J__a没有,在Groovy中表示为deffrequen__=[the:5hello:2world:2]
18.类变量即static变量,Groovy与J__a相同,staticStringname=山风小子,在Groovy也可写为staticname=山风小子
19.在varargs方法方面,Groovy与J__a稍有区别,如下所示J__a:// J__a: public void vararg__ethodType args { //do something}Groovy:def vararg__ethodType[] args { //do something}
20.引用当前对象,Groovy和J__a相同,在J__a中用this表示,在Groovy中也用this表示,而且在Groovy中,this可以出现在static范围中,指向所在类的类对象,本例中,this等同于ThisInStaticScope.class(J__a写法)或ThisInStaticScope(Groovy写法)class ThisInStaticScope { static { println this } // 请不要诧异,参数类型可以省略如果方法声明中有修饰关键字比如public,synchronized,static等,则返回值类型可以省略 static __inargs { println this }}
21.子类中调用父类方法,Groovy和J__a也相同,在J__a中super.methodName,在Groovy中super.methodName
22.命名空间的定义,Groovy和J__a相同,在J__a中packageedu.ecust.bluesun; 在Groovy中packageedu.ecust.bluesun (分号可省略)
23.在导入类方面,Groovy和J__a相同,在J__a中importedu.ecust.bluesun.GroovyTest; 在Groovy中importedu.ecust.bluesun.GroovyTest
24.List常量类型为j__a.util.ArrayList在J__a中没有,在Groovy中表示为deflist=[311Hello山风小子!]
25.在异常处理方面,Groovy与J__a相同,除了不强制程序员捕获检查异常checkedex__ption外这跟C#很像,如果我没记错的话: 并且在方法声明时,也可以不写throws语句
26.方法的默认参数,J__a中没有,Groovy中表示如下class Hello { //如果没有参数传入,默认打印出 Hello 山风小子 def greetname=山风小子 { printlnHello $name //也可省略括号 }}
27.在Groovy中,语句如果单独占一行的话,句尾的分号;可以省略,而在J__a中每条语句后面必须跟有分号;
28.在Groovy中,如果不是Boolean或boolean类型,非null或非空空字符串,[],[:]为true,null为false,而J__a中对象不可以表示true或false;如果是Boolean或boolean类型,与J__a中的一样
29.在Groovy中,万事万物都是对象!而J__a中不是这样,基本类型primitivetype就不是对象
30.在J__a中,Class对象表示为ClassName.class,而在Groovy中,可以直接用ClassName表示Class对象
31.Groovy会自动导入j__a.lang.*j__a.util.*j__a.net.*j__a.io.*j__a.__th.BigIntegerj__a.__th.BigDeci__l groovy.lang.*groovy.util.*,而J__a则只自动导入j__a.lang.*
32.Groovy不仅有:三元操作符,还有:两元操作符,但J__a只有:三元操作符Groovy:def a = null;// 如果a为“空”(null,空串,[],[:]),那么结果为:之后的那个值; 如果不为“空”,那么结果就是adef result = a : default resultprintln resulta = 山风小子result = a : default resultprintln result由上可知,Groovy几乎完全兼容J__a的语法,难怪‘江南白衣’称Groovy是J__a的‘___’;但由于Groovy不仅借鉴了J__a95%以上的特性,而且还借鉴了许多卓越的动态语言,比如PythonRuby等,使Groovy成为极其高效敏捷的编程语言,而不仅仅是J__a的副本所以其实J__a++可以作为Groovy的别名,即具有动态特性的J__a最后,我想补充一句Groovy的特性远不至所列的这些,比如还有Mixins,builder系列:__rkupBuilderSwingBuilder等,很多都是Groovy中有而J__a中没有,因此就不一一列举了,想继续深入学习Groovy,可访问Groovy____http://groovy.codehaus.orghttp://groovy.codehaus.org ,里面有很多例子和教程供大家参阅,也可以参考在下的Groovy高效编程系列(其中一些是在下的笔记)网上也有《GroovyInAction》___下载,大家不妨搜一下Groovy轻松入门——Grails实战基础篇http://___.blogj__a.net/BlueSUN/archive/2007/03/21/
105113.html在学习任何东西之前,最重要的是培养兴趣,Groovy世界最耀眼的技术之一--Grailshttp://___.grails.org相信大家早已耳闻,我将通过Grails实战系列文章向您展现Grails的迷人风采,使您__到Grails的魅力,以至疯狂地爱上Grails,并坠入Groovy的爱河学Groovy,Grails与学J__a一样,在实战之前需要搭建__环境,您可以在Groovy轻松入门--搭建Groovy__环境http://___.blogj__a.net/BlueSUN/archive/2007/03/17/
104391.html学习到如何搭建Groovy环境,之后我会讲一下如何搭建Grails环境,然后手把手地写个Demo程序告终,我还会抽空写篇“Groovy轻松入门--Grails实战之进阶篇”一,搭建Grails环境0,下载Grails http://dist.codehaus.org/grails/grails-bin-
0.
4.
2.ziphttp://dist.codehaus.org/grails/grails-bin-
1.
0.ziphttp://dist.codehaus.org/grails/grails-bin-
1.
0.ziphttp://dist.codehaus.org/grails/grails-bin-
0.
4.
2.zip,请留意朝花夕拾——GroovyGrailshttp://___.blogj__a.net/BlueSUN/archive/2007/04/23/
112978.html中的“最新版本”提示并解压到自己指定位置(我的位置是D:\D\MY_DEV\grails)1,设置环境变量GRAILS_HOME(注意大写),过程与“设置环境变量GROOVY_HOME”相似2,将%GRAILS_HOME%\bin添加到环境变量path中,过程与“将GROOVY_HOME目录下的bin追加到环境变量path中”相似(如果只想进行Grails__,可以不设GROOVY_HOME)二,创建GrailsDemo程序3,打开“命令行”,选择当前目录(我的为D:\Temp\grails_apps),在黑底白字的窗口中输入“grailscreate-appdemo”,不包括双引号“”,在您的屏幕中可以看到类似下面的输出结果D:\_DEV\grails_appsgrailscreate-appdemoWelcometoGrails
1.0-http://grails.org/Li__nsedunderApacheStandardLi__nse
2.0Grailshomeissetto:D:\D\MY_DEV\grails-
1.0BaseDirectory:D:\_DEV\grails_appsEnviro__entsettodevelopmentNote:NopluginscriptsfoundRunningscriptD:\D\MY_DEV\grails-
1.0\scripts\CreateApp.groovy [mkdir]Createddir:D:\_DEV\grails_apps\demo\src [mkdir]Createddir:D:\_DEV\grails_apps\demo\src\j__a [mkdir]Createddir:D:\_DEV\grails_apps\demo\src\groovy [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\controllers [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\servi__s [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\do__in [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\taglib [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\utils [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\views [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\views\layouts [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\i18n [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\conf [mkdir]Createddir:D:\_DEV\grails_apps\demo\test [mkdir]Createddir:D:\_DEV\grails_apps\demo\test\unit [mkdir]Createddir:D:\_DEV\grails_apps\demo\test\integration [mkdir]Createddir:D:\_DEV\grails_apps\demo\scripts [mkdir]Createddir:D:\_DEV\grails_apps\demo\web-app [mkdir]Createddir:D:\_DEV\grails_apps\demo\web-app\js [mkdir]Createddir:D:\_DEV\grails_apps\demo\web-app\css [mkdir]Createddir:D:\_DEV\grails_apps\demo\web-app\i__ges [mkdir]Createddir:D:\_DEV\grails_apps\demo\web-app\WEB-INF\classes [mkdir]Createddir:D:\_DEV\grails_apps\demo\web-app\META-INF [mkdir]Createddir:D:\_DEV\grails_apps\demo\lib [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\conf\spring [mkdir]Createddir:D:\_DEV\grails_apps\demo\grails-app\conf\hibernate[propertyfile]Creatingnewpropertyfile:D:\_DEV\grails_apps\demo\application.properties [copy]Copying2filestoD:\_DEV\grails_apps\demo [copy]Copying2filestoD:\_DEV\grails_apps\demo\web-app\WEB-INF [copy]Copying5filestoD:\_DEV\grails_apps\demo\web-app\WEB-INF\tld [copy]Copying87filestoD:\_DEV\grails_apps\demo\web-app [copy]Copying17filestoD:\_DEV\grails_apps\demo\grails-app [copy]Copying1filetoD:\_DEV\grails_apps\demo [copy]Copying1filetoD:\_DEV\grails_apps\demo [copy]Copying1filetoD:\_DEV\grails_apps\demo[propertyfile]Updatingpropertyfile:D:\_DEV\grails_apps\demo\application.propertiesCreatedGrailsApplicationatD:\_DEV\grails_apps/demoD:\_DEV\grails_apps通过“grailscreate-app”这个命令,Grails自动帮我们创建了__所需的工程环境其实您现在就已经拥有了一个可运行的Web应用程序,然后进入demo目录“cddemo”,输入“grailsrun-app”,回车,启动这个‘五脏俱全’的程序雏形,打开浏览器,输入http://localhost:8080/demohttp://localhost:8080/demo,回车,看到了吧:让我们继续吧,请停止这个程序Ctrl+C4,在“命令行”中输入“cddemo”,回车,以进入demo目录,然后再输入“grailscreate-do__in-classUser”创建do__inclass即类似于pojo的pogo,它对应MVC中的Model,不过由Grails自动创建的pogo是空的,需要自己添加属性,约束(constraints)等输出结果如下所示D:\_DEV\grails_apps\demograilscreate-do__in-classUserWelcometoGrails
1.0-http://grails.org/Li__nsedunderApacheStandardLi__nse
2.0Grailshomeissetto:D:\D\MY_DEV\grails-
1.0BaseDirectory:D:\_DEV\grails_apps\demoEnviro__entsettodevelopmentNote:NopluginscriptsfoundRunningscriptD:\D\MY_DEV\grails-
1.0\scripts\CreateDo__inClass.groovy [copy]Copying1filetoD:\_DEV\grails_apps\demo\grails-app\do__inCreated forUser [copy]Copying1filetoD:\_DEV\grails_apps\demo\test\integrationCreatedTestsforUserD:\_DEV\grails_apps\demo5,进入D:\Temp\grails_apps\demo\grails-app\do__in(这个目录中存放着所有的do__inclass),打开User.groovy,修改为如下内容class User { String name String password String toString { $name : $password } static constraints = { nameblank: false passwordblank: false size:
6..16 }} contraints这个类变量是定义一些约束的,比如name不能为空白,password不能为空白而且长度在6到16之间(包括6和16)6,在“命令行”中输入“grailsgenerate-allUser”,为User产生所有CRUD操作需要的代码(如控制器UserController.groovy)和页面(如list.gsp),输出结果如下所示D:\_DEV\grails_apps\demograilsgenerate-allUserWelcometoGrails
1.0-http://grails.org/Li__nsedunderApacheStandardLi__nse
2.0Grailshomeissetto:D:\D\MY_DEV\grails-
1.0BaseDirectory:D:\_DEV\grails_apps\demoEnviro__entsettodevelopmentNote:NopluginscriptsfoundRunningscriptD:\D\MY_DEV\grails-
1.0\scripts\GenerateAll.groovy [mkdir]Createddir:D:\_DEV\grails_apps\demo\web-app\WEB-INF\lib [mkdir]Createddir:C:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo\classes [groovyc]Compiling7sour__filestoC:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo\classes [mkdir]Createddir:C:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo\resour__s\grails-app\i18n[native2ascii]Converting10filesfromD:\_DEV\grails_apps\demo\grails-app\i18ntoC:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo\resour__s\grails-app\i18n [copy]Copying1filetoC:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo\classes [copy]Copying1filetoC:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo\resour__s [copy]Copying1filetoC:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo
[0]spring.GrailsWebApplicationContextRefreshingorg.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@2b2057:displayname[org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@2b2057];startupdate[TueFeb0523:26:45CST2008];rootofcontexthierarchy
[16]spring.GrailsWebApplicationContextBeanfactoryforapplicationcontext[org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@2b2057]:org.springframework.beans.factory.support.DefaultListableBeanFactory@eebf17Generatingviewsfordo__inclassUser...Generatingcontrollerfordo__inclassUser...Finishedgenerationfordo__inclassUserD:\_DEV\grails_apps\demo7,修改demo\grails-app\controllers\UserController.groovy的内容为 class UserController { def loginServi__ // 新增的代码 def index = { redirectaction:listparams:params } // the delete s__e and update actions only ac__pt POST requests def allowedMethods = [delete:POST s__e:POST update:POST] def list = { if!params.__x params.__x = 10 [ userList: User.list params ] } def show = { def user = User.get params.id if!user { flash.message = User not found with id ${params.id} redirectaction:list } else { return [ user : user ] } } def delete = { def user = User.get params.id ifuser { user.delete flash.message = User ${params.id} deleted redirectaction:list } else { flash.message = User not found with id ${params.id} redirectaction:list } } def edit = { def user = User.get params.id if!user { flash.message = User not found with id ${params.id} redirectaction:list } else { return [ user : user ] } } def update = { def user = User.get params.id ifuser { user.properties = params if!user.hasErrors user.s__e { flash.message = User ${params.id} updated redirectaction:showid:user.id } else { renderview:editmodel:[user:user] } } else { flash.message = User not found with id ${params.id} redirectaction:editid:params.id } } def create = { def user = new User user.properties = params return [user:user] } def s__e = { def user = new Userparams if!user.hasErrors user.s__e { flash.message = User ${user.id} created redirectaction:showid:user.id } else { renderview:createmodel:[user:user] } } // 新增的代码 def login = { if request.method == POST { User u = new User u.properties = params if !u.validate { renderview:login model:[user:u] } if params.name params.password { def user = loginServi__.checku if user { flash.message = Welcome ${user.name} renderview: ok model: [user: user] } else { flash.error = Invalid ${u.name} with ${u.password} renderview: login model: [user: u] } } else { renderview: login model: [user: u] } } }}大家或许也看到了LoginServi__这个类,我将在后面演示创建它,这个LoginServi__类封装了所有登陆相关的业务逻辑,Grails会自动将其注入到UserController中8,在“命令行”中,输入“grailscreate-servi__Login”,创建LoginServi__.groovy,输出D:\_DEV\grails_apps\demograilscreate-servi__LoginWelcometoGrails
1.0-http://grails.org/Li__nsedunderApacheStandardLi__nse
2.0Grailshomeissetto:D:\D\MY_DEV\grails-
1.0BaseDirectory:D:\_DEV\grails_apps\demoEnviro__entsettodevelopmentNote:NopluginscriptsfoundRunningscriptD:\D\MY_DEV\grails-
1.0\scripts\CreateServi__.groovy [copy]Copying1filetoD:\_DEV\grails_apps\demo\grails-app\servi__sCreatedServi__forLogin [copy]Copying1filetoD:\_DEV\grails_apps\demo\test\integrationCreatedServi__TestsforLoginD:\_DEV\grails_apps\demo9,修改demo\grails-app\servi__s\LoginServi__.groovy的内容为class LoginServi__ { boolean transactional = true def checkUser u { def user = User.findWherename: 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=__in / !-- 将Create User修改为Login -- titleLogin/title /head body div class=n__ span class=menuButtona class=home href=${createLinkTodir:}Home/a/span span class=menuButtong:link class=list action=listUser List/g:link/span /div div class=body !-- 将Create User修改为Login -- h1Login/h1 !-- 将flash.message修改为flash.error -- g:if test=${flash.error} !-- 将class=message修改为class=errors 将flash.message修改为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 !-- 将action=s__e修改为action=login -- g:form action=login method=post div class=dialog table tbody tr class=prop td valign=top class=name label for=nameName:/label /td td valign=top class=value ${hasErrorsbean:userfield:nameerrors} input type=text id=name name=name value=${fieldValuebean:userfield:name}/ /td /tr tr class=prop td valign=top class=name label for=passwordPassword:/label /td td valign=top class=value ${hasErrorsbean:userfield:passworderrors} input type=text __xlength=16 id=password name=password value=${fieldValuebean:userfield:password}/ /td /tr /tbody /table /div div class=buttons !-- 将value=Create修改为value=Login -- span class=buttoninput class=s__e type=submit value=Login //span /div /g:form /div /body/htmlok.gsp:g:if test=${flash.message} div class=message${flash.message}/div/g:ifName: ${user.name} brPassword: ${user.password}11,修改demo\grails-app\conf\BootStrap.groovy,初始化数据库将一个User实例保存到数据库grails自带hsqldb和jetty中,内容如下class BootStrap { def init = { servletContext - new Username: demo password:
123456.s__e } def destroy = { }} 12,在“命令行”中,输入“grailsrun-app”,运行我们的Web应用,输出如下D:\_DEV\grails_apps\demograilsrun-appWelcometoGrails
1.0-http://grails.org/Li__nsedunderApacheStandardLi__nse
2.0Grailshomeissetto:D:\D\MY_DEV\grails-
1.0BaseDirectory:D:\_DEV\grails_apps\demoEnviro__entsettodevelopmentNote:NopluginscriptsfoundRunningscriptD:\D\MY_DEV\grails-
1.0\scripts\RunApp.groovy [groovyc]Compiling4sour__filestoC:\DocumentsandSettings\Daniel\.grails\
1.0\projects\demo\classesRunningGrailsapplication..2008-02-0523:46:
08.912::INFO: LoggingtoSTDERRviaorg.mortbay.log.StdErrLog2008-02-0523:46:
08.066::INFO: jetty-
6.
1.42008-02-0523:46:
08.347::INFO: NoTransaction__nagerfound-ifyourwebapprequiresonepleaseconfigureone.2008-02-0523:46:
09.081:/demo:INFO: Setwebapprootsystemproperty:demo=[D:\_DEV\grails_apps\demo\web-app\]2008-02-0523:46:
09.081:/demo:INFO: InitializingLog4Jfrom[file:C:\DocumentsandSettings\Daniel/.grails/
1.0/projects/demo/resour__s/log4j.properties]2008-02-0523:46:
09.113:/demo:INFO: InitializingSpringrootWebApplicationContext
[0]spring.GrailsWebApplicationContextRefreshingorg.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@5fa___:displayname[org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@5fa___];startupdate[TueFeb0523:46:14CST2008];parent:org.springframework.web.context.support.XmlWebApplicationContext@1fef80a
[0]spring.GrailsWebApplicationContextBeanfactoryforapplicationcontext[org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext@5fa___]:org.springframework.beans.factory.support.DefaultListableBeanFactory@aa4c7c2008-02-0523:46:
21.590:/demo:INFO: InitializingSpringFrameworkServletgrails2008-02-0523:46:
21.871::INFO: StartedSelectChannelConnector@
0.
0.
0.0:8080Serverrunning.Browsetohttp://localhost:8080/demo 13,打开浏览器,输入http://localhost:8080/demo/user/loginhttp://localhost:8080/demo/login/login ,在Name处输入demo,Password处输入123456,__‘Login’,跳转到成功页面WelcomedemoName:demoPassword:123456如果您对Grails的工程目录不太熟悉,我这里为大家提供了一张表,详细地描述了各目录的用途《Grails权威指南》http://___.blogj__a.net/BlueSUN/archive/2007/05/17/
118030.html表3-
1.Grails工程目录目录名称相关描述grails-app此目录包含了Grails应用程序的核心工件coreartifact+conf此目录包含了诸如DevelopmentDataSour__.groovy的配置文件+controllers此目录包含了处理请求request的控制器controller,Grails控制器将在第7章中进行讲解+do__in此目录包含了领域模型do__inmodel,领域模型将在第4章进行讲解+i18n此目录包含了用于国际化的消息束messagebundle(译者注指的是properties文件,如messages.properties)+servi__s此目录包含了封装业务逻辑的servi__文件,servi__将在第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和J__a资源+j__a此目录包含了待编译的J__a源文件+groovy此目录包含了待编译的Groovy源文件web-app此目录包含了Web应用程序的资源(CSS,J__aScript等)注Grails
1.0已将hibernate和spring两个目录移到grails-app\conf目录下了,而grails-test目录也更名为test,test目录下有integration目录和unit目录,分别存放集成测试代码和单元测试代码想象一下用您平时做项目时所用的框架组合(比如SSH)来创建同样的Web应用程序,您立刻会__,Grails让我们专注于业务逻辑,而不用浪费时间在那些scaffoldingcode如配置文件上从今天开始,您不用再羡慕那些Ruby程序员所用的RoR了,您大可以使用Grails来高效__Web应用您也可以访问Grails____(http://___.grails.orghttp://___.grails.org)进一步学习Groovy轻松入门——Grails实战之GORM篇(更新于2007年4月8日)http://___.blogj__a.net/BlueSUN/archive/2007/04/05/1086__.htmlGORM就是以前我刚学Groovy没多久时想实现的功能,它使__人员不需要关心数据库方面,也不需要任何配置,只需专心用OO思想设计自己的系统,还有一个好处就是__时不用备份数据库,因为GORM会自动帮你建表以及约束(但数据库需要你自己建),让我们来看一下用Grails__是多么简单高效吧!在Grails
0.6+中,配置稍有不同,详见朝花夕拾——GroovyGrailshttp://___.blogj__a.net/BlueSUN/archive/2007/04/archive/2007/06/archive/2007/04/23/
112978.html在写域类时,无须添加与业务无关的属性,比如在用Hibernate时,我们需要(不强制)在类中定义id,但用GORM时,id无须自己声明,GORM会帮我们自动添加id和versionGORM通过反射机制获得域类属___决定数据库字段类型,所以在定义域类时不要使用def关键字来定义属性,务必明确定义属性类型,比如在下面的域类Article中,用String来定义content(而不是defcontent),在默认情况下,String映射到数据库中的字段类型是VARCHAR(Date映射到数据库中的字段类型是DATETIME),如果通过类变量contraints定义了String的长度范围,且长度过长,映射到数据库中的字段类型会变为TEXT,十分智能eg.classArticle{ DatedateAdded //Date映射到数据库中的字段类型是DATETIME Stringcontent staticconstraints={ contentblank:falsesize:
0..65535//如果没有定义content的大小范围,它在数据库中类型为VARCHAR最大长度是255, //显然不满足我们的需求,这样定义后,数据库中的字段类型会变为TEXT }}如果将数据源projectname/grails-app/conf/XXXDataSour__中的StringdbCreate=update,Grails会自动帮我们同步内存和数据库中域类对象的状态,这点是很方便的,不需要在每次修改对象后,update了(GORM中的s__e相当于Hibernate中的s__eOrUpdate),其好处犹如J__a中,new出一个对象,当不再使用此对象时,不需要自行delete一样在实际__中您就会体会到了下面让我们看一下GORM中的1:1,1:N,N:1,N:N以及继承关系映射1,一对一关系classDog{ Stringname Tailtail// 狗有一条尾巴}classTail{ floatsize Dogowner // 尾巴也知道自己属于那只狗}现在Dog和Tail的一对一关系是双向的,当然你也可以去掉Tail类中的owner属性或Dog类中的tail属性,使一对一关系变为单向的级联删除当Dog对象被删除时,则Dog对象所引用的Tail对象也将被相应删除;同样地,当Tail对象被删除时,Tail对象所引用的Dog对象也将被相应删除如果你认为Tail被切除后,Dog应该还活着,即Tail对象删除后,Tail对象所应用的Dog对象不应该被删除,那么我们可以通过在Tail类中声明类变量belongsTo来实现,在这个场景中,我们将Tail改为classTail{ floatsize Dogowner // 尾巴也知道自己属于那只狗 staticbelongsTo=Dog//注意是static的}级联更新/保存当Dog对象更新/保存,Dog对象所引用的Trail对象也更新/保存;反之亦然2,一对多,多对一关系classDog{ Stringname staticha__any=[feet:Foot]//通过声明类变量ha__any,来定义Dog‘一’这方有多Foot}classFoot{ floatsize Dogowner staticbelongsTo=Dog//在一对多,多对一关系中,默认‘多’方belongsTo‘一’方}关于保存,更新和删除与一对一关系相同,都是级联更新/保存和级联删除,当Dog被删除时,由于FootbelongsTo属于Dog,所以Dog对象所引用的所有Foot对象全被删除;而当Foot对象被删除时,Dog对象不会被删除这是通过类变量belongsTo实现的3,多对多关系classTeacher{ Stringname staticha__any=[students:Student]}classStudent{ Stringname staticha__any=[teachers:Teacher] staticbelongsTo=Teacher //在多对多关系中,至少有一方声明类变量belongsTo}更新/保存在多对多关系中,相对一对一,一对多,多对一关系中要特殊点,就是只有‘拥有方’可以级联更新/保存,比如在本例中,由于StudentbelongsToTeacher,所以Teacher是‘拥有方’,Teacher的更新/保存将引起Teacher对象所引用的所有Student对象的更新/保存删除也有点特殊,‘拥有方’被删除后,它所引用的对象不会被删除,你必须自己删除它们,否则它们将成为‘孤儿’4,继承关系classBase{...}classDerivedextendsBase{...}只要定义类,无需任何配置,够简单吧用Grails__就是这么简单快捷,域类定义好了之后,剩下的事情,比如建表,约束等,Grails全帮您自动搞定,很省心!Grails____上有很多文档供参考,对GORM的进一步学习,您可以看一下GORMhttp://___.grails.org/GORMhttp://___.grails.org/GORM+-+Defining+relationshipsGroovy轻松入门——Grails实战之Ajax篇http://___.blogj__a.net/BlueSUN/archive/2007/05/11/
116851.htmlAjax虽是“旧酒装新瓶”,但其威力着实不小近两年来可谓红透半边天,它之所以能为大众接受,其中一个很大的原因就是提高了用户浏览体验,能更逼真的模拟出GUI界面好了,Ajax的益处就说到这里,下面让我们看下Grails是如何帮助我们方便地应用Ajax的:如果您对下面说设计的内容有点不解,那么您可以先看一下Groovy轻松入门——Grails实战基础篇http://___.blogj__a.net/BlueSUN/archive/2007/05/archive/2007/03/21/
105113.html,然后开始我们的Ajax之旅1在命令行中输入“grailscreate-appAjaxDemo”(注意不带引号“”)创建一个Grailsproject,我将它命名为AjaxDemo D:\Temp\grails_appsgrails create-app AjaxDemoWelcome to Grails
0.5 - http://grails.org/Li__nsed under Apache Standard Li__nse
2.0Grails home is set to: D:\D\MY_DEV\grails-
0.5Base Directory: D:\Temp\grails_appsEnviro__ent set to productionNote: No plugin scripts foundRunning script D:\D\MY_DEV\grails-
0.5\scripts\CreateApp.groovy [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\src [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\src\j__a [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\src\groovy [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\src\test [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\controllers [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\jobs [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\servi__s [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\do__in [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\taglib [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\utils [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\views [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\views\layouts [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\i18n [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\conf [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-tests [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\scripts [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\js [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\css [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\i__ges [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\classes [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\META-INF [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\lib [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\spring [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\hibernate[propertyfile] Creating new property file: D:\Temp\grails_apps\AjaxDemo\application.properties [copy] Copying 2 files to D:\Temp\grails_apps\AjaxDemo [copy] Copying 2 files to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF [copy] Copying 5 files to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\tld [copy] Copying 119 files to D:\Temp\grails_apps\AjaxDemo\web-app [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-app\conf [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-app\conf [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-app\conf [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-app\conf [copy] Copying 13 files to D:\Temp\grails_apps\AjaxDemo\grails-app [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\plugins\core\grails-app\taglib [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\plugins\core\grails-app\utils [copy] Copying 7 files to D:\Temp\grails_apps\AjaxDemo\plugins\core\grails-app\taglib [copy] Copying 4 files to D:\Temp\grails_apps\AjaxDemo\plugins\core\grails-app\utils [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\spring [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo[propertyfile] Updating property file: D:\Temp\grails_apps\AjaxDemo\application.propertiesCreated Grails Application at D:\Temp\grails_apps/AjaxDemoD:\Temp\grails_apps2,“cdAjaxDemo”,进入AjaxDemo目录,输入“grailscreate-do__in-classUser”,创建一个域类User D:\Temp\grails_apps\AjaxDemograils create-do__in-class UserWelcome to Grails
0.5 - http://grails.org/Li__nsed under Apache Standard Li__nse
2.0Grails home is set to: D:\D\MY_DEV\grails-
0.5Base Directory: D:\Temp\grails_apps\AjaxDemoEnviro__ent set to productionRunning script D:\D\MY_DEV\grails-
0.5\scripts\CreateDo__inClass.groovy [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-app\do__inCreated for User [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-testsCreated Tests for UserD:\Temp\grails_apps\AjaxDemo3,“grailsgenerate-allUser”,生成scaffoldingcode(如list.gsp等)D:\Temp\grails_apps\AjaxDemograils generate-all UserWelcome to Grails
0.5 - http://grails.org/Li__nsed under Apache Standard Li__nse
2.0Grails home is set to: D:\D\MY_DEV\grails-
0.5Base Directory: D:\Temp\grails_apps\AjaxDemoEnviro__ent set to productionRunning script D:\D\MY_DEV\grails-
0.5\scripts\GenerateAll.groovyCompiling sour__s [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\lib [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\spring [copy] Copying 34 files to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\lib [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\grails-app\i18n [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\grails-app\views [copy] Copying 2 files to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\grails-app\views [mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\templates\scaffolding [copy] Copying 5 files to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\templates\scaffolding[native2ascii] Converting 7 files from D:\Temp\grails_apps\AjaxDemo\grails-app\i18n to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\grails-app\i18n [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\spring [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\classes [copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\web-app\WEB-INF\classesGenerating views for do__in class [User]Generating list view for do__in class [User]list view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\list.gspGenerating show view for do__in class [User]Show view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\show.gspGenerating edit view for do__in class [User]Edit view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\edit.gspGenerating create view for do__in class [User]Create view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\create.gspGenerating controller for do__in class [User]Controller generated at .\grails-app\controllers\UserController.groovyD:\Temp\grails_apps\AjaxDemo4,修改AjaxDemo\grails-app\controllers\UserController.groovy的内容为 class UserController { def index = { redirectaction:listparams:params } // the delete s__e and update actions only // ac__pt POST requests def allowedMethods = [delete:POST s__e:POST update:POST] def list = { if!params.__xparams.__x = 10 [ userList: User.list params ] } def show = { [ user : User.get params.id ] } def delete = { def user = User.get params.id ifuser { user.delete flash.message = User ${params.id} deleted. redirectaction:list } else { flash.message = User not found with id ${params.id} redirectaction:list } } def edit = { def user = User.get params.id if!user { flash.message = User not found with id ${params.id} redirectaction:list } else { return [ user : user ] } } def update = { def user = User.get params.id ifuser { user.properties = params ifuser.s__e { redirectaction:showid:user.id } else { renderview:editmodel:[user:user] } } else { flash.message = User not found with id ${params.id} redirectaction:editid:params.id } } def create = { def user = new User user.properties = params return [user:user] } def s__e = { def user = new User user.properties = params ifuser.s__e { redirectaction:showid:user.id } else { renderview:createmodel:[user:user] } } // 自己添加的Closure ajax定义 def ajax = {} // 自己添加的Closure sayHello定义 def sayHello = { render [${new Date}] Hello ${params.name} }}添加sayHello闭包的目的很明显,因为客户端需要调用那___还要添加ajax这个闭包呢?其实添加ajax这个闭包的目的是使http://localhost:8080/AjaxDemo/user/ajax这个请求合法化,否则会发生404错误,找不到页面HTTPERROR:404NotFoundRequestURI=/AjaxDemo/user/ajaxPoweredbyJetty://http://jetty.mortbay.org/所以被客户端请求的每个gsp页面,都需要在相应的Controller中添加以gsp文件名为变量名的Closure,如上面的ajax.gsp和ajax={}所示,其中Closure中可以添加相关代码,我们这里仅仅是做Ajax的演示,所以就不需要代码5,在AjaxDemo\grails-app\views\user目录下,新建ajax.gsp,用来演示remoteLink的用法,内容为g:j__ascript library=prototype /div id=helloContent will be displayed here/divg:remoteLink action=sayHello params=[name:BlueSUN] update=helloSayHello/g:remoteLinkparams表示要传递的参数,而update表示返回结果显示的地方,注意update=hello中的hello对应于div的id,表示结果将显示于div所在处__链接后的界面[Fri__y1117:46:47CST2007]HelloBlueSUNSayHellohttp://___.blogj__a.net/AjaxDemo/user/sayHelloname=BlueSUN6,修改AjaxDemo\grails-app\views\user\ajax.gsp,演示formRemote的用法,内容为g:j__ascript library=prototype /div id=helloContent will be displayed here/divdiv id=error/divg:remoteLink action=sayHello params=[name:BlueSUN] update=helloSay Hello/g:remoteLinkhr /g:formRemote name=test url=[controller:useraction:sayHello] update=[suc__ss:hellofailure:error] input type=text name=name value=BlueSUN / input type=submit value=Say Hello //g:formRemote 原本用params传递的参数,现在可以以form的形式传递了,将想传递的内容输入name的textfield中即可默认值我设为BlueSUN,现在我将值改为terry,__SayHello按钮,结果如下[Fri__y1118:16:17CST2007]HelloterrySayHellohttp://___.blogj__a.net/AjaxDemo/user/sayHelloname=BlueSUNTopofFormBottomofForm7,修改AjaxDemo\grails-app\views\user\ajax.gsp和AjaxDemo\grails-app\controllers\UserController.groovy,演示remoteField的用法ajax.gsp:g:j__ascript library=prototype /div id=helloContent will be displayed here/divdiv id=error/divg:remoteLink action=sayHello params=[name:BlueSUN] update=helloSay Hello/g:remoteLinkhr /g:formRemote name=test url=[controller:useraction:sayHello] update=[suc__ss:hellofailure:error] input type=text name=name value=BlueSUN / input type=submit value=Say Hello //g:formRemote hr /g:remoteField action=sayHello2 update=hello name=name value= /UserController.groovy: class UserController { def index = { redirectaction:listparams:params } // the delete s__e and update actions only // ac__pt POST requests def allowedMethods = [delete:POST s__e:POST update:POST] def list = { if!params.__xparams.__x = 10 [ userList: User.list params ] } def show = { [ user : User.get params.id ] } def delete = { def user = User.get params.id ifuser { user.delete flash.message = User ${params.id} deleted. redirectaction:list } else { flash.message = User not found with id ${params.id} redirectaction:list } } def edit = { def user = User.get params.id if!user { flash.message = User not found with id ${params.id} redirectaction:list } else { return [ user : user ] } } def update = { def user = User.get params.id ifuser { user.properties = params ifuser.s__e { redirectaction:showid:user.id } else { renderview:editmodel:[user:user] } } else { flash.message = User not found with id ${params.id} redirectaction:editid:params.id } } def create = { def user = new User user.properties = params return [user:user] } def s__e = { def user = new User user.properties = params ifuser.s__e { redirectaction:showid:user.id } else { renderview:createmodel:[user:user] } } // 自己添加的Closure ajax定义 def ajax = {} // 自己添加的Closure sayHello定义 def sayHello = { render [${new Date}] Hello ${params.name} } // 自己添加的Closure sayHello2定义 def sayHello2 = { render [${new Date}] Hello ${params.value} }}由于用remoteField传递过来的参数名为value,又为了保留以前的演示,所以再定义一个sayHello2闭包,注意是params.value而非params.name输入“BlueSUN”,请注意输入时页面的相应更新效果,结果界面输入到一半,即输入“Blue”[Fri__y1118:34:03CST2007]HelloBlueSayHellohttp://___.blogj__a.net/AjaxDemo/user/sayHelloname=BlueSUNTopofFormBottomofForm紧接着输入“SUN”[Fri__y1118:32:42CST2007]HelloBlueSUNSayHellohttp://___.blogj__a.net/AjaxDemo/user/sayHelloname=BlueSUNTopofFormBottomofForm8,修改AjaxDemo\grails-app\views\user\ajax.gsp,演示remoteFunction的用法,内容为g:j__ascript library=prototype /div id=helloContent will be displayed here/divdiv id=error/divg:remoteLink action=sayHello params=[name:BlueSUN] update=helloSay Hello/g:remoteLinkhr /g:formRemote name=test url=[controller:useraction:sayHello] update=[suc__ss:hellofailure:error] input type=text name=name value=BlueSUN / input type=submit value=Say Hello //g:formRemote hr /g:remoteField action=sayHello2 update=hello name=name value= /hr /button onClick=${remoteFunctionaction:sayHelloupdate:[suc__ss:hello failure:error] params:\name=\ + \BlueSUN\}Say Hello/button__SayHello按钮后,结果页面[Fri__y1118:48:37CST2007]HelloBlueSUNSayHellohttp://___.blogj__a.net/AjaxDemo/user/sayHelloname=BlueSUNTopofFormBottomofFormSayHello9,Grails也可以利用Ajax异步显示Server端返回的页面,新建页面AjaxDemo\grails-app\views\user\result.gsp:html head meta http-equiv=Content-Type content=text/html; charset=UTF-8/ meta name=layout content=__in / titleResult Page/title /head body div class=n__ span class=menuButtona href=${createLinkTodir:}Home/a/span /div div class=body h1${name}/h1 /div /body/html修改AjaxDemo\grails-app\controllers\UserController.groovy: class UserController { def index = { redirectaction:listparams:params } // the delete s__e and update actions only // ac__pt POST requests def allowedMethods = [delete:POST s__e:POST update:POST] def list = { if!params.__xparams.__x = 10 [ userList: User.list params ] } def show = { [ user : User.get params.id ] } def delete = { def user = User.get params.id ifuser { user.delete flash.message = User ${params.id} deleted. redirectaction:list } else { flash.message = User not found with id ${params.id} redirectaction:list } } def edit = { def user = User.get params.id if!user { flash.message = User not found with id ${params.id} redirectaction:list } else { return [ user : user ] } } def update = { def user = User.get params.id ifuser { user.properties = params ifuser.s__e { redirectaction:showid:user.id } else { renderview:editmodel:[user:user] } } else { flash.message = User not found with id ${params.id} redirectaction:editid:params.id } } def create = { def user = new User user.properties = params return [user:user] } def s__e = { def user = new User user.properties = params ifuser.s__e { redirectaction:showid:user.id } else { renderview:createmodel:[user:user] } } // 自己添加的Closure ajax定义 def ajax = {} // 自己添加的Closure sayHello定义 def sayHello = { render [${new Date}] Hello ${params.name} } // 自己添加的Closure sayHello2定义 def sayHello2 = { render [${new Date}] Hello ${params.value} } // 自己添加的Closure displayResultPage定义 def displayResultPage = { renderview:result model:[name:params.name] }}修改AjaxDemo\grails-app\views\user\ajax.gsp:g:j__ascript library=prototype /div id=helloContent will be displayed here/divdiv id=error/divg:remoteLink action=sayHello params=[name:BlueSUN] update=helloSay Hello/g:remoteLinkhr /g:formRemote name=test url=[controller:useraction:sayHello] update=[suc__ss:hellofailure:error] input type=text name=name value=BlueSUN / input type=submit value=Say Hello //g:formRemote hr /g:remoteField action=sayHello2 update=hello name=name value= /hr /button onClick=${remoteFunctionaction:sayHelloupdate:[suc__ss:hello failure:error] params:\name=\ + \BlueSUN\}Say Hello/buttonhr /g:formRemote name=test url=[controller:useraction:displayResultPage] update=[suc__ss:hellofailure:error] input type=text name=name value=BlueSUN / input type=submit value=Say Hello //g:formRemote 输入“terry”,__SayHello按钮,结果页面(样式的丢失是因为在ajax.gsp中没有声明css,目的是抓重点,抛开一切琐碎的内容)最后要提醒大家一点,如果要使用中文,请将中文写在AjaxDemo\grails-app\i18n\messages_zh_CN.properties中,然后用g:messagecode=key/来显示正如各位所看到的那样,在Grails中使用Ajax就是那么简单,此外DWR插件即将出炉,到时利用DWR来__Ajax应用也将变的十分方便:如果您急需使用DWR,请参考《Groovy轻松入门——Grails实战之遗留框架利用篇http://___.blogj__a.net/BlueSUN/archive/2007/05/archive/2007/06/22/____
21.html》Groovy轻松入门——Grails实战之遗留数据库处理篇(更新于
2007.
09.23)http://___.blogj__a.net/BlueSUN/archive/2007/06/06/
122434.html由于在过去一段时间内,已有多位朋友向我询问如何用Grails处理遗留数据库,为了回答这个问题我给出一个实例,并适当讲解,不足之处,敬请谅解在Grails
0.6+中,配置稍有不同,详见朝花夕拾——GroovyGrailshttp://___.blogj__a.net/BlueSUN/archive/2007/06/archive/2007/04/23/
112978.html我使用的数据库为MySQL5,其中存在一个名为legacy_dev的sche__,legacy_dev中有一张表叫user1,创建Grails应用程序,我将它命名为legacy grailscreate-applegacy2,创建一个域类User grailscreate-do__in-classUser3,修改grails-app\do__in\User.groovy的内容,如下所示class User { String userId String password static constraints = { userIdblank:false __xSize:16 passwordblank:false __xSize:45 }} 4,生成与域类User相关的所有Grails应用程序工件artifact grailsgenerate-allUser5,将grails-app\conf\DevelopmentDataSour__.groovy的内容改为class DevelopmentDataSour__ { boolean pooling = true // 将这行注释掉 //String dbCreate = update // one of create create-dropupdate // url和driver要正确 String url = jdbc:mysql://localhost:3306/legacy_dev String driverClassName = com.mysql.jdbc.Driver String username = root String password = // 这里为您的__ :}6,自行配置Hibernate hibernate.cfg.xmlxml version=
1.0 encoding=UTF-8!DOCTYPE hibernate-configuration PUBLIC -//Hibernate/Hibernate Configuration DTD
3.0//EN http://hibernate.sour__forge.net/hibernate-configuration-
3.
0.dtdhibernate-configuration session-factory property name=connection.driver_classcom.mysql.jdbc.Driver/property property name=connection.urljdbc:mysql://localhost:3306/legacy_dev/property property name=connection.usernameroot/property property name=connection.password/property property name=connection.pool_size1/property property name=dialectorg.hibernate.dialect.MySQLDialect/property property name=current_session_context_classthread/property property name=cache.provider_classorg.hibernate.cache.NoCacheProvider/property property name=show_sqltrue/property property name=hbm2ddl.autovalidate/property __pping resour__=User.hbm.xml/ /session-factory/hibernate-configurationUser.hbm.xmlxml version=
1.0!DOCTYPE hibernate-__pping PUBLIC -//Hibernate/Hibernate __pping DTD
3.0//ENhttp://hibernate.sour__forge.net/hibernate-__pping-
3.
0.dtdhibernate-__pping class name=User table=user id name=userId column=user_id type=j__a.lang.String length=16 generator class=assigned / /id property name=password column=password type=j__a.lang.String length=45 / /class/hibernate-__pping最后,别忘了修改grails-app\controllers\UserController.groovy以及各GSP的代码(试验代码时,请不要在EditUser页面中更新用户的userId,否则出发生异常,因为‘主键’不可更改在自己的应用程序中,可以disable掉EditUser页面中的UserId文本域)UserController.groovy class UserController { def index = { redirectaction:listparams:params } // the delete s__e and update actions only // ac__pt POST requests def allowedMethods = [delete:POST s__e:POST update:POST] def list = { if!params.__xparams.__x = 10 [ userList: User.list params ] } def show = { //[ user : User.get params.id ] [ user : User.findByUserIdparams.id ] } def delete = { //def user = User.get params.id def user = User.findByUserIdparams.id ifuser { user.delete flash.message = User ${params.id} deleted. redirectaction:list } else { flash.message = User not found with id ${params.id} redirectaction:list } } def edit = { //def user = User.get params.id def user = User.findByUserIdparams.id if!user { flash.message = User not found with id ${params.id} redirectaction:list } else { return [ user : user ] } } def update = { //def user = User.get params.id def user = User.findByUserIdparams.id ifuser { user.properties = params ifuser.s__e { //redirectaction:showid:user.id redirectaction:showid:user.userId } else { renderview:editmodel:[user:user] } } else { flash.message = User not found with id ${params.id} redirectaction:editid:params.id } } def create = { def user = new User user.properties = params return [user:user] } def s__e = { def user = new User user.properties = params ifuser.s__e { //redirectaction:showid:user.id redirectaction:showid:user.userId } else { renderview:createmodel:[user:user] } }}grails-app\views\user\list.gsp html head meta http-equiv=Content-Type content=text/html; charset=UTF-8/ meta name=layout content=__in / titleUser List/title /head body div class=n__ span class=menuButtona href=${createLinkTodir:}Home/a/span span class=menuButtong:link action=createNew User/g:link/span /div div class=body h1User List/h1 g:if test=${flash.message} div class=message ${flash.message} /div /g:if table thead tr !-- g:sortableColumn property=id title=Id / -- g:sortableColumn property=userId title=User Id / g:sortableColumn property=password title=Password / th/th /tr /thead tbody g:each in=${userList} tr !-- td${it.id.encodeAsHTML}/td -- td${it.userId.encodeAsHTML}/td td${it.password.encodeAsHTML}/td td class=actionButtons !-- span class=actionButtong:link action=show id=${it.id}Show/g:link/span -- span class=actionButtong:link action=show id=${it.userId}Show/g:link/span /td /tr /g:each /tbody /table div class=paginateButtons g:paginate total=${User.count} / /div /div /body/htmlgrails-app\views\user\show.gsp html head meta http-equiv=Content-Type content=text/html; charset=UTF-8/ meta name=layout content=__in / titleShow User/title /head body div class=n__ span class=menuButtona href=${createLinkTodir:}Home/a/span span class=menuButtong:link action=listUser List/g:link/span span class=menuButtong:link action=createNew User/g:link/span /div div class=body h1Show User/h1 g:if test=${flash.message} div class=message${flash.message}/div /g:if div class=dialog table tbody !-- tr class=prop td valign=top class=nameId:/td td valign=top class=value${user.id}/td /tr -- tr class=prop td valign=top class=nameUser Id:/td td valign=top class=value${user.userId}/td /tr tr class=prop td valign=top class=namePassword:/td td valign=top class=value${user.password}/td /tr /tbody /table /div div class=buttons g:form controller=user !-- input type=hidden name=id value=${user.id} / -- input type=hidden name=id value=${user.userId} / span class=buttong:actionSubmit value=Edit //span span class=buttong:actionSubmit value=Delete //span /g:form /div /div /body/htmlgrails-app\views\user\create.gsp html head meta http-equiv=Content-Type content=text/html; charset=UTF-8/ meta name=layout content=__in / titleCreate User/title /head body div class=n__ span class=menuButtona href=${createLinkTodir:}Home/a/span span class=menuButtong:link action=listUser List/g:link/span /div div class=body h1Create User/h1 g:if test=${flash.message} div class=message${flash.message}/div /g:if g:hasErrors bean=${user} div class=errors g:renderErrors bean=${user} as=list / /div /g:hasErrors g:form action=s__e method=post div class=dialog table tbody tr class=proptd valign=top class=namelabel for=userIdUser Id:/label/tdtd valign=top class=value ${hasErrorsbean:userfield:userIderrors}input type=text name=userId value=${user.userId.encodeAsHTML}//td/tr tr class=proptd valign=top class=namelabel for=passwordPassword:/label/tdtd valign=top class=value ${hasErrorsbean:userfield:passworderrors}input type=text name=password value=${user.password.encodeAsHTML}//td/tr /tbody /table /div div class=buttons span class=formButton input type=submit value=Create/input /span /div /g:form /div /body/htmlgrails-app\views\user\edit.gsp html head meta http-equiv=Content-Type content=text/html; charset=UTF-8/ meta name=layout content=__in / titleEdit User/title /head body div class=n__ span class=menuButtona href=${createLinkTodir:}Home/a/span span class=menuButtong:link action=listUser List/g:link/span span class=menuButtong:link action=createNew User/g:link/span /div div class=body h1Edit User/h1 g:if test=${flash.message} div class=message${flash.message}/div /g:if g:hasErrors bean=${user} div class=errors g:renderErrors bean=${user} as=list / /div /g:hasErrors!-- div class=prop span class=nameId:/span span class=value${user.id}/span /div -- g:form controller=user method=post !-- input type=hidden name=id value=${user.id} / -- input type=hidden name=id value=${user.userId} / div class=dialog table tbody tr class=proptd valign=top class=namelabel for=userIdUser Id:/label/tdtd valign=top class=value ${hasErrorsbean:userfield:userIderrors}input type=text name=userId value=${user.userId.encodeAsHTML}//td/tr tr class=proptd valign=top class=namelabel for=passwordPassword:/label/tdtd valign=top class=value ${hasErrorsbean:userfield:passworderrors}input type=text name=password value=${user.password.encodeAsHTML}//td/tr /tbody /table /div div class=buttons span class=buttong:actionSubmit value=Update //span span class=buttong:actionSubmit value=Delete //span /div /g:form /div /body/html好了,整个处理过程已经呈现给大家了,希望对大家有用:Groovy轻松入门——Grails实战之遗留框架利用篇http://___.blogj__a.net/BlueSUN/archive/2007/06/22/____
21.html很多用户(其中也包括我)害怕失去那些自己所熟悉的东西,比如框架,__环境等在这篇随笔中,您将看到如何在Grails中利用我们所熟知的框架其中涉及到配置Spring,配置web.xml和配置dwr.xml,而配置Hibernate在《http://___.blogj__a.net/BlueSUN/archive/2007/06/archive/2007/06/06/
122434.htmlGroovy轻松入门——Grails实战之遗留数据库处理篇http://___.blogj__a.net/BlueSUN/archive/2007/06/06/
122434.html》中已经讲解过了,所以本篇随笔不再累述我以利用DWR框架为例稍作讲解Grails无需任何配置,但不阻止我们配置在Grails
0.6+中,配置稍有不同,详见朝花夕拾——GroovyGrailshttp://___.blogj__a.net/BlueSUN/archive/2007/06/archive/2007/06/archive/2007/04/23/
112978.html1,“grailscreate-appdwrDemo”,创建Grails工程2,将dwr.jarhttps://dwr.dev.j__a.net/files/documents/2427/56756/dwr.jar放到lib目录中(我使用的是DWR2)3,给web-app\WEB-INF\web.template.xml添加如下内容(我们可以通过修改web.template.xml来达到配置web.xml的目的) servlet servlet-namedwr-invoker/servlet-name servlet-classorg.directwebremoting.servlet.DwrServlet/servlet-class init-param param-namedebug/param-name param-valuetrue/param-value /init-param /servlet servlet-__pping servlet-namedwr-invoker/servlet-name url-pattern/dwr/*/url-pattern /servlet-__ppingweb-app\WEB-INF\web.template.xml的最终内容如下所示xml version=
1.0 encoding=UTF-8web-app version=
2.4 xmlns=http://j__a.sun.com/xml/ns/j2ee xmlns:xsi=http://___.w
3.org/2001/XMLSche__-instan__ xsi:sche__Location=http://j__a.sun.com/xml/ns/j2ee http://j__a.sun.com/xml/ns/j2ee/web-app_2_
4.xsd context-param param-namelog4jConfigLocation/param-name param-value/WEB-INF/classes/log4j.properties/param-value /context-param context-param param-namecontextConfigLocation/param-name param-value/WEB-INF/applicationContext.xml/param-value /context-param context-param param-namewebAppRootKey/param-name param-valuedwrtest/param-value /context-param filter filter-namesitemesh/filter-name filter-classorg.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter/filter-class /filter filter filter-namecharEncodingFilter/filter-name filter-classorg.springframework.web.filter.DelegatingFilterProxy/filter-class init-param param-nametargetBeanName/param-name param-valuecharacterEncodingFilter/param-value /init-param init-param param-nametargetFilterLifecycle/param-name param-valuetrue/param-value /init-param /filter filter-__pping filter-namecharEncodingFilter/filter-name url-pattern/*/url-pattern /filter-__pping filter-__pping filter-namesitemesh/filter-name url-pattern/*/url-pattern /filter-__pping listener listener-classorg.springframework.web.util.Log4jConfigListener/listener-class /listener listener listener-classorg.codehaus.groovy.grails.web.context.GrailsContextLoaderListener/listener-class /listener !-- Grails dispatcher servlet -- servlet servlet-namegrails/servlet-name servlet-classorg.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet/servlet-class load-on-startup1/load-on-startup /servlet !-- The Groovy Server Pages servlet -- servlet servlet-namegsp/servlet-name servlet-classorg.codehaus.groovy.grails.web.pages.GroovyPagesServlet/servlet-class /servlet servlet-__pping servlet-namegsp/servlet-name url-pattern*.gsp/url-pattern /servlet-__pping !--DWRservlet -- servlet servlet-namedwr-invoker/servlet-name servlet-classorg.directwebremoting.servlet.DwrServlet/servlet-class init-param param-namedebug/param-name param-valuetrue/param-value /init-param /servlet servlet-__pping servlet-namedwr-invoker/servlet-name url-pattern/dwr/*/url-pattern /servlet-__pping welcome-file-list !-- The order of the welcome pages is important. JBoss deployment will break if index.gsp is first in the list. -- welcome-fileindex.jsp/welcome-file welcome-fileindex.gsp/welcome-file /welcome-file-list jsp-config taglib taglib-urihttp://j__a.sun.com/jsp/jstl/core/taglib-uri taglib-location/WEB-INF/tld/c.tld/taglib-location /taglib taglib taglib-urihttp://j__a.sun.com/jsp/jstl/fmt/taglib-uri taglib-location/WEB-INF/tld/fmt.tld/taglib-location /taglib taglib taglib-urihttp://___.springframework.org/tags/taglib-uri taglib-location/WEB-INF/tld/spring.tld/taglib-location /taglib taglib taglib-urihttp://grails.codehaus.org/tags/taglib-uri taglib-location/WEB-INF/tld/grails.tld/taglib-location /taglib /jsp-config/web-app4,在src\j__a下,建立如下目录结构 edu └─ecust ├─servi__ │ │ Servi__.j__a │ │ │ └─impl │ SomeServi__Impl.j__a │ └─test Hello.j__aHello.j__apackage edu.ecust.test;import edu.ecust.servi__.Servi__;public class Hello { private Servi__ servi__; public void setServi__Servi__ servi__ { this.servi__ = servi__; } public String helloString name { boolean result = servi__.doSomethingname; return result Welcome + name : Hello + name; }}Servi__.j__apackage edu.ecust.servi__;public inte_____ Servi__ { public boolean doSomethingString name;}SomeServi__Impl.j__apackage edu.ecust.servi__.impl;import edu.ecust.servi__.Servi__;public class SomeServi__Impl implements Servi__ { public boolean doSomethingString name { if Daniel.equalsname { return true; } else { return false; } }}5,修改spring\resour__s.xml的内容(我们可以通过修改resour__s.xml来达到配置Spring的目的)xml version=
1.0 encoding=UTF-8beans xmlns=http://___.springframework.org/sche__/beans xmlns:xsi=http://___.w
3.org/2001/XMLSche__-instan__ xsi:sche__Location=http://___.springframework.org/sche__/beans http://___.springframework.org/sche__/beans/spring-beans-
2.
0.xsd bean id=someServi__ class=edu.ecust.servi__.impl.SomeServi__Impl / bean id=welcome class=edu.ecust.test.Hello property name=servi__ ref=someServi__ / /bean/beans6,在web-app\WEB-INF目录下新建dwr.xml,修改内容如下xml version=
1.0 encoding=UTF-8!DOCTYPE dwr PUBLIC -//GetAhead Limited//DTD Direct Web Remoting
2.0//EN http://___.getahead.ltd.uk/dwr/dwr
20.dtddwr allow create creator=spring j__ascript=welcome param name=beanName value=welcome / /create /allow/dwr7,在web-app\js目录下新建hello.js,修改内容如下function hello { var name = $name.value; welcome.helloname callback;} function callbackmsg { DWRUtil.setValueresult msg;} 8,“grailscreate-controllerUser”创建一个UserController9,修改grails-app\controllers\UserController.groovy内容class UserController { def hello = {}}10,在grails-app\views\user目录下新建新建hello.gsp,修改内容如下html head script type=text/j__ascript src=%=request.getContextPath%/dwr/inte_____/welcome.js/script script type=text/j__ascript src=%=request.getContextPath%/dwr/engine.js/script script type=text/j__ascript src=%=request.getContextPath%/dwr/util.js/script script type=text/j__ascript src=%=request.getContextPath%/js/hello.js/script /head body Name: input id=name type=text onKeyup=hello;/ div id=result/div /body/html11,“grailsrun-app”,启动这个Web应用程序12,访问http://localhost:8080/dwrDemo/user/hello,并输入Daniel,注意观察效果Name:HelloDanName:WelcomeDanielGroovy轻松入门——Grails实战之WebFlow篇http://___.blogj__a.net/BlueSUN/archive/2007/09/08/
143544.htmlSpringWebFlow是Spring家族中的一位成员,他能简化Web应用的__在Grails
0.6中就集成了SpringWebFlow这一Web应用__利器下面通过一个实例向大家展示一下在Grails中如何方便的使用SpringWebFlow1,“grailscreate-appWebFlowDemo”,输出如下D:\_DEV\grails_appsgrails create-app WebFlowDemoWelcome to Grails
0.6 - http://grails.org/Li__nsed under Apache Standard Li__nse
2.0Grails home is set to: D:\D\MY_DEV\grails
0.6Base Directory: D:\_DEV\grails_appsEnviro__ent set to developmentNote: No plugin scripts foundRunning script D:\D\MY_DEV\grails
0.6\scripts\CreateApp.groovyOverriding previous definition of referen__ to groovyJarSet [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\src [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\src\j__a [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\src\groovy [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\controllers [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\servi__s [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\do__in [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\taglib [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\utils [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\views [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\views\layouts [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\i18n [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\test [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\test\unit [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\test\integration [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\scripts [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\js [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\css [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\i__ges [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\classes [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\META-INF [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\lib [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf\spring [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf\hibernate[propertyfile] Creating new property file: D:\_DEV\grails_apps\WebFlowDemo\application.properties [copy] Copying 2 files to D:\_DEV\grails_apps\WebFlowDemo [copy] Copying 2 files to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF [copy] Copying 5 files to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\tld [copy] Copying 131 files to D:\_DEV\grails_apps\WebFlowDemo\web-app [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf [copy] Copying 13 files to D:\_DEV\grails_apps\WebFlowDemo\grails-app [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\grails-app\conf\spring [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo[propertyfile] Updating property file: D:\_DEV\grails_apps\WebFlowDemo\application.propertiesCreated Grails Application at D:\_DEV\grails_apps/WebFlowDemoD:\_DEV\grails_apps2,“cdWebFlowDemo”,进入工程目录3,“grailscreate-do__in-classUser”,创建一个域类User,输出如下D:\_DEV\grails_apps\WebFlowDemograils create-do__in-class UserWelcome to Grails
0.6 - http://grails.org/Li__nsed under Apache Standard Li__nse
2.0Grails home is set to: D:\D\MY_DEV\grails
0.6Base Directory: D:\_DEV\grails_apps\WebFlowDemoEnviro__ent set to developmentNote: No plugin scripts foundRunning script D:\D\MY_DEV\grails
0.6\scripts\CreateDo__inClass.groovy [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\grails-app\do__inCreated for User [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\test\integrationCreated Tests for UserD:\_DEV\grails_apps\WebFlowDemo4,将grails-app\do__in\User.groovy修改为如下内容class User implements Serializable { String username String password}5,“grailsgenerate-allUser”,生成所有与域类User相关的目录和文件,输出如下D:\_DEV\grails_apps\WebFlowDemograils generate-all UserWelcome to Grails
0.6 - http://grails.org/Li__nsed under Apache Standard Li__nse
2.0Grails home is set to: D:\D\MY_DEV\grails
0.6Base Directory: D:\_DEV\grails_apps\WebFlowDemoEnviro__ent set to developmentNote: No plugin scripts foundRunning script D:\D\MY_DEV\grails
0.6\scripts\GenerateAll.groovy [mkdir] Created dir: C:\Documents and Settings\Daniel\.grails\
0.6\projects\WebFlowDemo\classesCompiling 5 sour__ files to C:\Documents and Settings\Daniel\.grails\
0.6\projects\WebFlowDemo\classes [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\grails-app\i18n [copy] Copying 8 files to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\grails-app\i18n [copy] Copying 1 file to D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\spring [copy] Copying 1 file to C:\Documents and Settings\Daniel\.grails\
0.6\projects\WebFlowDemo\classes [copy] Copying 1 file to C:\Documents and Settings\Daniel\.grails\
0.6\projects\WebFlowDemo\classesGenerating views for do__in class User Generating controller for do__in class User Finished generation for do__in class UserD:\_DEV\grails_apps\WebFlowDemo6,将grails-app\controllers\UserController.groovy修改为如下内容 class UserController { def index = { redirectaction:listparams:params } // the delete s__e and update actions only ac__pt POST requests def allowedMethods = [delete:POST s__e:POST update:POST] def list = { if!params.__xparams.__x = 10 [ userList: User.list params ] } def show = { [ user : User.get params.id ] } def delete = { def user = User.get params.id ifuser { user.delete flash.message = User ${params.id} deleted. redirectaction:list } else { flash.message = User not found with id ${params.id} redirectaction:list } } def edit = { def user = User.get params.id if!user { flash.message = User not found with id ${params.id} redirectaction:list } else { return [ user : user ] } } def update = { def user = User.get params.id ifuser { user.properties = params ifuser.s__e { flash.message = User ${params.id} updated. redirectaction:showid:user.id } else { renderview:editmodel:[user:user] } } else { flash.message = User not found with id ${params.id} redirectaction:editid:params.id } } def create = { def user = new User user.properties = params return [user:user] } def s__e = { def user = new User user.properties = params ifuser.s__e { flash.message = User ${user.id} created. redirectaction:showid:user.id } else { renderview:createmodel:[user:user] } } def loginSystemFlow = { login { onlogin { if daniel != params.username || 123 != params.password { flash.message = username or password is invalid defuser=newUser user.properties=params flash.user=user return error } else { // 仅仅用来演示如何使用flow scope flow.message = Welcome ${params.username} } }.to ok onregister.to showRegisterView } ok showRegisterView }}onlogin{...}.took表示__login按钮后所要去的页面为ok,如果验证失败(daniel != params.username || 123 != params.password),则利用内置的error,使用户返回login页面;而onregister.to showRegisterView是类似的,不再累述7,在grails-app\views\user\目录下新建一个名为“loginSystem”的子目录,该名称为UserController.groovy中的loginSystemFlow的“loginSystem”相对应8,在grails-app\views\user\loginSystem\目录下新建login.gsp,ok.gsp,showRegisterView.gsp三个GSP文件(这三个文件的文件名与 def loginSystemFlow = { login { ... } ok showRegisterView }中粗体突显的state名相对应,其中login为startstate,而ok和showRegisterView为endstate),并将其内容修改为login.gsphtml head meta http-equiv=Content-Type content=text/html; charset=UTF-8 / meta name=layout content=__in / titleLogin Page/title /head body div class=n__ span class=menuButtona class=home href=${createLinkTodir:}Home/a /span /div div class=body h1 Login Page /h1 g:if test=${message } div class=message ${message } /div /g:if g:form action=loginSystem method=post div class=dialog table tbody tr class=prop td valign=top class=name label for=username Username: /label /td td valign=top class=value ${hasErrorsbean:userfield:usernameerrors} input type=text id=username name=username value=${user.username.encodeAsHTML} / /td /tr tr class=prop td valign=top class=name label for=password Password: /label /td td valign=top class=value ${hasErrorsbean:userfield:passworderrors} input type=text id=password name=password value=${user.password.encodeAsHTML} / /td /tr /tbody /table /div div class=buttons span class=buttong:submitButton class=s__e name=login value=Login/g:submitButton /span /div g:link action=loginSystem event=registerRegister/g:link /g:form /div /body/htmlok.gsp${message }br /g:link action=loginSystemback to login page/g:linkshowRegisterView.gspThis is a register page br /g:link action=loginSystemback to login page/g:link9,“grailsrun-app”,启动Grails应用,输出如下D:\_DEV\grails_apps\WebFlowDemograils run-appWelcome to Grails
0.6 - http://grails.org/Li__nsed under Apache Standard Li__nse
2.0Grails home is set to: D:\D\MY_DEV\grails
0.6Base Directory: D:\_DEV\grails_apps\WebFlowDemoEnviro__ent set to developmentNote: No plugin scripts foundRunning script D:\D\MY_DEV\grails
0.6\scripts\RunApp.groovy [mkdir] Created dir: D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\libCompiling 1 sour__ files to C:\Documents and Settings\Daniel\.grails\
0.6\projects\WebFlowDemo\classesRunning Grails application..2007-09-08 00:12:
24.443::INFO: Logging to STDERR via org.mortbay.log.StdErrLog2007-09-08 00:12:
24.521::INFO: jetty-
6.
1.42007-09-08 00:12:
26.425:/WebFlowDemo:INFO: Set web app root system property: @grails.project.key@ = [D:\_DEV\grails_apps\WebFlowDemo\web-app\]2007-09-08 00:12:
26.425:/WebFlowDemo:INFO: Initializing Log4J from [D:\_DEV\grails_apps\WebFlowDemo\web-app\WEB-INF\classes\log4j.properties]2007-09-08 00:12:
26.472:/WebFlowDemo:INFO: Loading Spring root WebApplicationContext
[9282] hibernate.ConfigurableLocalSessionFactoryBean Building new Hibernate SessionFactory
[9922] mvc.GrailsUrlHandler__pping Neither url__p nor __ppings set on ______UrlHandler__pping
[12750] commons.GrailsConfigUtils [GrailsContextLoader] Grails application loaded.
[12797] mvc.GrailsWebRequestFilter Initializing filter grailsWebRequest
[12797] mvc.GrailsWebRequestFilter Filter grailsWebRequest configured suc__ssfully
[12797] filter.Url__ppingsFilter Initializing filter url__pping
[12797] filter.Url__ppingsFilter Initializing filter url__pping
[12797] filter.Url__ppingsFilter Filter url__pping configured suc__ssfully
[12797] filter.Url__ppingsFilter Filter url__pping configured suc__ssfully
[12797] filter.GrailsReloadServletFilter Initializing filter reloadFilter
[12797] filter.GrailsReloadServletFilter Filter reloadFilter configured suc__ssfully[12__1] servlet.GrailsDispatcherServlet Initializing servlet grails
[12954] servlet.GrailsDispatcherServlet FrameworkServlet grails: initialization started2007-09-08 00:12:
36.562:/WebFlowDemo:INFO: Loading WebApplicationContext for Spring FrameworkServlet grails
[13485] servlet.GrailsDispatcherServlet Using context class [org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext] for servlet grails
[13485] servlet.GrailsDispatcherServlet Using MultipartResolver [org.springframework.web.multipart.commons.Common__ultipartResolver@dd7404]
[13485] servlet.GrailsDispatcherServlet Using LocaleResolver [org.springframework.web.servlet.i18n.SessionLocaleResolver@ebbf5c]
[13500] servlet.GrailsDispatcherServlet Unable to locate ThemeResolver with name themeResolver: using default [org.springframework.web.servlet.theme.FixedThemeResolver@192c766]
[13516] servlet.GrailsDispatcherServlet No HandlerAdapters found in servlet grails: using default
[13532] servlet.GrailsDispatcherServlet Unable to locate RequestToViewNameTranslator with name viewNameTranslator: using default [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@a40575]
[13532] servlet.GrailsDispatcherServlet Using MultipartResolver [org.springframework.web.multipart.commons.Common__ultipartResolver@dd7404]
[13532] servlet.GrailsDispatcherServlet FrameworkServlet grails: initialization completed in 578 ms
[13532] servlet.GrailsDispatcherServlet Servlet grails configured suc__ssfully2007-09-08 00:12:
37.374::INFO: Started SelectChannelConnector@
0.
0.
0.0:8080Server running. Browse to http://localhost:8080/WebFlowDemo10,访问http://localhost:8080/WebFlowDemo/user/loginSystem11,输入任意登录信息,并按一下Login按钮,我直接按Login按钮:12,输入daniel和123,并按一下Login按钮Welcomedanielbacktologinpagehttp://___.blogj__a.net/WebFlowDemo/user/loginSystem13,__backtologinpage链接,在__login页面上的Register链接Thisisaregisterpagebacktologinpagehttp://___.blogj__a.net/WebFlowDemo/user/loginSystem一个最简单的SpringWebFlow应用完成最后告诉大家一个好消息,《Grails权威指南》最晚将在下个月出版,喜欢Grails的朋友到时可以买一本系统地学习一下Grails这个强大的框架,为自己今后的__注入新的活力关于此书的一些说明可以看一下《Grails权威指南》译者序(草稿)http://___.blogj__a.net/BlueSUN/archive/2007/09/archive/2007/07/29/
133113.html。