频道直达:新闻 - 组网 - 安全 - 服务器 - 存储 - 系统 - 应用 - 开发 - 数据库 - 前沿 - 技术人 - 培训 - 求职 - 读书 - 教程 - 专题 - 产品 - 案例 - 技术圈 - 博客 - BBS
51CTO.COM_中国领先的IT技术网站
找资料:

Groovy轻松入门——Grails实战之Ajax篇

作者: 山风小子 出处:蛟龍居 2007-10-16 14:00    砖    好    评论   进入论坛
阅读提示:Ajax虽是“旧酒装新瓶”,但其威力着实不小。近两年来可谓红透半边天,它之所以能为大众接受,其中一个很大的原因就是提高了用户浏览体验,能更逼真的模拟出GUI界面。

Ajax虽是“旧酒装新瓶”,但其威力着实不小。近两年来可谓红透半边天,它之所以能为大众接受,其中一个很大的原因就是提高了用户浏览体验,能更逼真的模拟出GUI界面。好了,Ajax的益处就说到这里,下面让我们看下Grails是如何帮助我们方便地应用Ajax的:

如果您对下面说设计的内容有点不解,那么您可以先看一下 Groovy轻松入门——Grails实战基础篇,然后开始我们的Ajax之旅。

1, 在命令行中输入:“grails create-app AjaxDemo”(注意:不带引号“”)创建一个Grails project,我将它命名为AjaxDemo:
D:\Temp\grails_apps>grails create-app AjaxDemo

Welcome to Grails 0.5 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\D\MY_DEV\grails-0.5

Base Directory: D:\Temp\grails_apps
Environment set to production
Note: No plugin scripts found
Running 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\java
[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\services
[mkdir] Created dir: D:\Temp\grails_apps\AjaxDemo\grails-app\domain
[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\images
[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.properties
Created Grails Application at D:\Temp\grails_apps/AjaxDemo
D:\Temp\grails_apps>


2,“cd AjaxDemo”,进入AjaxDemo目录,输入“grails create-domain-class User”,创建一个域类User:

D:\Temp\grails_apps\AjaxDemo>grails create-domain-class User

Welcome to Grails 0.5 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\D\MY_DEV\grails-0.5

Base Directory: D:\Temp\grails_apps\AjaxDemo
Environment set to production
Running script D:\D\MY_DEV\grails-0.5\scripts\CreateDomainClass.groovy
[copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-app\domain
Created  for User
[copy] Copying 1 file to D:\Temp\grails_apps\AjaxDemo\grails-tests
Created Tests for User
D:\Temp\grails_apps\AjaxDemo>


3,“grails generate-all User”,生成scaffolding code(如:list.gsp等):

D:\Temp\grails_apps\AjaxDemo>grails generate-all User

Welcome to Grails 0.5 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: D:\D\MY_DEV\grails-0.5

Base Directory: D:\Temp\grails_apps\AjaxDemo
Environment set to production
Running script D:\D\MY_DEV\grails-0.5\scripts\GenerateAll.groovy
Compiling sources
[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\i1
8n
[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\classes
Generating views for domain class [User]
Generating list view for domain class [User]
list view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\list.gsp
Generating show view for domain class [User]
Show view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\show.gsp
Generating edit view for domain class [User]
Edit view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\edit.gsp
Generating create view for domain class [User]
Create view generated at D:\Temp\grails_apps\AjaxDemo\.\grails-app\views\user\create.gsp
Generating controller for domain class [User]
Controller generated at .\grails-app\controllers\UserController.groovy
D:\Temp\grails_apps\AjaxDemo>

4,修改AjaxDemo\grails-app\controllers\UserController.groovy的内容为:

class  UserController {
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  =  {
[ user : User.get( params.id ) ]
}

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.save()) {
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()
user.properties  =  params
if (user.save()) {
redirect(action:show,id:user.id)
}
else  {
render(view: ' create ' ,model:[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错误,找不到页面:
HTTP ERROR: 404

Not Found

RequestURI=/AjaxDemo/user/ajax

Powered by Jetty://

所以被客户端请求的 每个 gsp页面,都需要在相应的Controller中添加以gsp文件名为变量名的Closure,如上面的ajax.gsp和ajax = {}所示,其中Closure中可以添加相关代码,我们这里仅仅是做Ajax的演示,所以就不需要代码

5,在AjaxDemo\grails-app\views\user目录下,新建ajax.gsp,用来演示remoteLink的用法,内容为:

< g:javascript  library ="prototype"   />


< div  id ="hello" > Content will be displayed here </ div >

< g:remoteLink  action ="sayHello"  params ="[name:'BlueSUN']" 

update ="hello" >Say Hello </ g:remoteLink >


params表示要传递的参数,而update表示返回结果显示的地方,注意update="hello"中的hello对应于div的id,表示结果将显示于div所在处。

点击链接后的界面:
[Fri May 11 17:46:47 CST 2007] Hello, BlueSUN
Say Hello

6,修改AjaxDemo\grails-app\views\user\ ajax.gsp,演示formRemote的用法,内容为:

<g:javascript library="prototype" />
<div id="hello">Content will be displayed here</div>
<div id="error"></div>

<g:remoteLink action="sayHello" params="[name:'BlueSUN']"

update="hello">Say Hello</g:remoteLink>

<hr />

<g:formRemote name="test" url="[controller:'user',action:'sayHello']"

update="[success:'hello',failure:'error']">
<input type="text" name="name" value="BlueSUN" />
<input type="submit" value="Say Hello" />
</g:formRemote >


原本用params传递的参数,现在可以以form的形式传递了,将想传递的内容输入name的textfield中即可。

默认值我设为BlueSUN,现在我将值改为terry,点击Say Hello按钮,结果如下:
[Fri May 11 18:16:17 CST 2007] Hello, terry
Say Hello

7,修改AjaxDemo\grails-app\views\user\ ajax.gsp和AjaxDemo\grails-app\controllers\UserController.groovy,演示remoteField的用法:
ajax.gsp:

<g:javascript library="prototype" />


<div id="hello">Content will be displayed here</div>
<div id="error"></div>

<g:remoteLink action="sayHello" params="[name:'BlueSUN']"

update="hello">Say Hello</g:remoteLink>

<hr />

<g:formRemote name="test" url="[controller:'user',action:'sayHello']"

update="[success:'hello',failure:'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 = { 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 = {
[ user : User.get( params.id ) ]
}

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.save()) {
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()
user.properties = params
if(user.save()) {
redirect(action:show,id:user.id)
}
else {
render(view:'create',model:[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 May 11 18:34:03 CST 2007] Hello, Blue
Say Hello


紧接着输入“SUN”
[Fri May 11 18:32:42 CST 2007] Hello, BlueSUN
Say Hello


8,修改AjaxDemo\grails-app\views\user\ ajax.gsp,演示remoteFunction的用法,内容为:

<g:javascript library="prototype" />


<div id="hello">Content will be displayed here</div>
<div id="error"></div>

<g:remoteLink action="sayHello" params="[name:'BlueSUN']"

update="hello">Say Hello</g:remoteLink>

<hr />

<g:formRemote name="test" url="[controller:'user',action:'sayHello']"

update="[success:'hello',failure:'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="${remoteFunction(action:'sayHello',

update:[success:'hello', failure:'error'], params:'\'name=\' + \'BlueSUN\'')}">

Say Hello</button>


点击Say Hello按钮后,结果页面:

[Fri May 11 18:48:37 CST 2007] Hello, BlueSUN
Say Hello
Say Hello

9,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 ="main"   />
< title > Result Page </ title >
</ head >
< body >
< div  class ="nav" >
< span  class ="menuButton" >
< a  href ="${createLinkTo(dir:'')}" > Home </ a ></ span >
</ div >
< div  class ="body" >
< h1 > ${name} </ h1 >
</ div >
</ body >
</ html >


修改AjaxDemo\grails-app\controllers\UserController.groovy:

class  UserController {
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  =  {
[ user : User.get( params.id ) ]
}

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.save()) {
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()
user.properties  =  params
if (user.save()) {
redirect(action:show,id:user.id)
}
else  {
render(view: ' create ' ,model:[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  =  {
render(view: ' result ' , model:[name:params.name])
}
}


修改AjaxDemo\grails-app\views\user\ajax.gsp:

< g:javascript  library ="prototype"   />


< div  id ="hello" > Content will be displayed here </ div >
< div  id ="error" ></ div >

< g:remoteLink  action ="sayHello"  params ="[name:'BlueSUN']" 

update ="hello" > Say Hello </ g:remoteLink >

< hr  />

< g:formRemote  name ="test"  url ="[controller:'user',action:'sayHello']" 

update ="[success:'hello',failure:'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 ="${remoteFunction(action:'sayHello',

update:[success:'hello', failure:'error'], params:'\'name=\' + \'BlueSUN\'')}"

> Say Hello </ button >

< hr  />

< g:formRemote  name ="test"  url ="[controller:'user',action:'displayResultPage']" 

update ="[success:'hello',failure:'error']" >
< input  type ="text"  name ="name"  value ="BlueSUN"   />
< input  type ="submit"  value ="Say Hello"   />
</ g:formRemote  >


输入“terry”,点击Say Hello按钮,结果页面(样式的丢失是因为在ajax.gsp中没有声明css,目的是抓重点,抛开一切琐碎的内容):

最后要提醒大家一点,如果要使用中文,请将中文写在AjaxDemo\grails-app\i18n\messages_zh_CN.properties中,然后用<g:message code="key" />来显示。

【责任编辑:dizzarz TEL:(010)68476606】

专题
Groovy开发技术
解析Ajax开发框架 走进Ajax开发应用
Ajax明天会HOT还是OVER?
微软的Ajax:Atlas(ASP.net AJAX)
AJAX 51CTO技术座谈会
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 领 先 的 IT 技 术 网 站 ·
技 术 成 就 梦 想
·Java基础教程 (查看81024次)
·UML类图详解 (查看72498次)
·C++是垃圾语言?! (查看42631次)
·C#技术开发指南 (查看40232次)
·UML统一建模语言 (查看39205次)
·Java编程开发手册 (1198个砖)
·Java基础教程 (431个砖)
·C#技术开发指南 (311个砖)
·.NET开发手册 (254个砖)
·PB开发教程 (223个砖)
·Java编程开发手册 (658个好)
·Java基础教程 (578个好)
·.NET开发手册 (282个好)
·PB开发教程 (213个好)
·Delphi开发技术手册 (200个好)
订阅技术快讯
电子杂志下载
名称:SQL Server数据库管理精品黄皮书
简介:书中文章经过精挑细选,便于用户能根据自己的实际工作和学习,快速在本书寻找到相关资料。内容涵盖了SQL Server的安装与升级、语句查询、数据备份和恢复、自动化任务、数据同步、数据字典、安全和预防、性能和优化、集群等各方面应用信息,以及DBA管理人员在数据库管理工作中
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。