Ajax虽是“旧酒装新瓶”,但其威力着实不小。近两年来可谓红透半边天,它之所以能为大众接受,其中一个很大的原因就是提高了用户浏览体验,能更逼真的模拟出GUI界面。好了,Ajax的益处就说到这里,下面让我们看下Grails是如何帮助我们方便地应用Ajax的:
如果您对下面说设计的内容有点不解,那么您可以先看一下 Groovy轻松入门——Grails实战基础篇,然后开始我们的Ajax之旅。
1, 在命令行中输入:“grails create-app AjaxDemo”(注意:不带引号“”)创建一个Grails project,我将它命名为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:
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等):
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
所以被客户端请求的 每个 gsp页面,都需要在相应的Controller中添加以gsp文件名为变量名的Closure,如上面的ajax.gsp和ajax = {}所示,其中Closure中可以添加相关代码,我们这里仅仅是做Ajax的演示,所以就不需要代码
5,在AjaxDemo/grails-app/views/user目录下,新建ajax.gsp,用来演示remoteLink的用法,内容为:
< 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所在处。
点击链接后的界面:
Say Hello
6,修改AjaxDemo/grails-app/views/user/ ajax.gsp,演示formRemote的用法,内容为:
< 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 >
默认值我设为BlueSUN,现在我将值改为terry,点击Say Hello按钮,结果如下:
7,修改AjaxDemo/grails-app/views/user/ ajax.gsp和AjaxDemo/grails-app/controllers/UserController.groovy,演示remoteField的用法:
ajax.gsp:
< 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} "
}
}