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
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" />来显示。
正如各位所看到的那样,在Grails中使用Ajax就是那么简单,此外DWR插件即将出炉,到时利用DWR来开发Ajax应用也将变的十分方便 :)
如果您急需使用DWR,请参考《
Groovy轻松入门——Grails实战之遗留框架利用篇
》
附:
朝花夕拾——Groovy & Grails
posted on 2007-05-11 19:24
山风小子 阅读(8492)
评论(9) 编辑 收藏 所属分类:
Groovy & Grails 、
Ajax