内容简介
- 控制controller、model、view之间的作用
- 实现自定义url和永久链接
- 使用过滤器
- 使用service让业务逻辑和页面跳转分离
- 数据绑定和错误处理
- 使用command对象,处理比较棘手的验证
- 上传和读取照片文件
一、控制controller、model、view之间的作用
controller的要领
http://ip:端口/应用程序名/controller/action/参数id
1、显示用户所有发帖
在controllers/com.grailsinacition.PostController/建立一个timeline action
1 def timeline = { 2 def user = User.findByUserId(params.id) 3 [ user : user ] 4 }
我们需要访问这个action时的地址就是http://localhost:8080/hubbub/post/timeline/userid
增加一个视图,将action返回的内容显示到页面上,视图的路径为post/timeline
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Timeline for ${user.profile.fullName} 5 </title> 6 <meta name="layout" content="main" /> 7 </head> 8 9 <body> 10 <h1> 11 Timeline for ${user.profile.fullName} 12 </h1> 13 14 <div class="allPosts"> 15 <g:each in="${user.posts}" var="post"> 16 <div class="postEntry"> 17 <div class="postText">${post.content}</div> 18 <div class="postDate">${post.dateCreated}</div> 19 </div> 20 </g:each> 21 </div> 22 </body> 23 </html>
如果不想让action和view使用同一个页面来渲染,action的返回值可以这样表示
render(view: "user_timeline", model: [ user: user ])
那么访问的页面就应该是post/user_timeline/userid
2、增加新帖
一般增加新帖和显示历史帖都放在一个界面显示,所以增加新帖只需要在显示帖的页面增加一个form
修改post/timeline
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Timeline for ${user.profile.fullName} 5 </title> 6 <meta name="layout" content="main" /> 7 </head> 8 9 <body> 10 <h1> 11 Timeline for ${user.profile.fullName} 12 </h1> 13 14 <div id="newPost"> 15 <h3>What is ${user.profile.fullName} hacking on right now?</h3> 16 <p> 17 <g:form action="addPost" id="${params.id}"> 18 <g:textArea id='postContent' name="content" rows="3" cols="50"/><br/> 19 <g:submitButton name="post" value="Post"/> 20 </g:form> 21 </p> 22 </div> 23 24 <div class="allPosts"> 25 <g:each in="${user.posts}" var="post"> 26 <div class="postEntry"> 27 <div class="postText">${post.content}</div> 28 <div class="postDate">${post.dateCreated}</div> 29 </div> 30 </g:each> 31 </div> 32 </body> 33 </html>
form提交给addPost,所以在PostController中增加一个addPost闭包处理,addPost负责插入表单数据,并返回页面
1 def addPost = { 2 def user = User.findByUserId(params.id) 3 if (user) { 4 def post = new Post(params) 5 user.addToPosts(post) 6 if (user.save()) { 7 flash.message = "Successfully created Post" 8 } else { 9 user.discard() 10 flash.message = "Invalid or empty post" 11 } 12 } else { 13 flash.message = "Invalid User Id" 14 } 15 redirect(action: 'timeline', id: params.id) 16 }
这个闭包里有一些提示消息(flash.message),为了让这些错误提示消息能正常的反馈到页面,现在修改一下post/timeline
1 ...... 2 </h1> 3 4 <g:if test="${flash.message}"> 5 <div class="flash">${flash.message}</div> 6 </g:if> 7 8 <div id="newPost"> 9 ......
请求的作用域
| 作用域 | 范围 |
page |
当前页面范围 (默认) |
request |
当前请求范围 |
| flash | 它可以在下一次请求中有效 |
session |
用户session范围 |
application |
全局范围 |
当我们在uri上直接访问http://localhost:8080/hubbub/post/timeline时,会默认请求index,我们的index是没有参数的,所以系统会出现找不到参数的错误,所以这里给一个默认的id供默认请求使用
1 def index = { 2 if (!params.id) { 3 params.id = "admin" 4 redirect(action: 'timeline', params: params) 5 } 6 }
另外一种默认页面的处理方式是
def defaultAction = 'timeline'
这样,只要访问http://localhost:8080/hubbub/post,页面也会跳转到timeline,这就是重定向的一种方法,关于重定向还有下面几种方法
1、直接跳转到指定action
redirect(action:'timeline')
2、直接跳转到指定的controller/action/params
redirect(controller: 'post', action:'timeline', id: newUser.userId)
3、复杂参数跳转
redirect(controller: 'post', action:'timeline',params: [fullName: newUser.profile.fullName,email: newUser.profile.email ])
4、不带参数的跳转,有两种方式(controler/action、uri)
redirect(controller: 'post', action:'timeline')
redirect(uri: '/post/timeline')
5、还可以跳转到外部连接
redirect(url: 'http://www.google.com?q=hubbub')
浙公网安备 33010602011771号