Grails 1.2参考文档速读(10):Controller
- 线程安全:每次请求创建新实例
- Controller – Action两级
- 缺省URL Mapping:/controller/action
- 文件名以Controller结尾
- 文件位置:grails-app/controllers
- 创建命令:grails create-controller
- 在Controller文件内,Action是闭包
class BookController {
def list = {
...
}
}
- 如果Controller只有一个action,那么它就是缺省action
- 使用defaultAction属性指定action名字
- 名字为index的action
- 返回Map:[ book : Book.get( params.id ) ]
- 不明确指明返回一个Model,那么Model就由Controller的属性组成。注意,正是因为Grails保证了Controller对于每一个请求都会新创建一个实例,我们才能利用这种实例变量。
- 返回Spring的ModelAndView:return new ModelAndView("/book/list", [ bookList : favoriteBooks ])
- 没有指定View,那么就查找(jsp文件优先)grails-app/views/controller/action.gsp
- 指 定View:render(view:“view名”, model:模型)。如:render(view:“display”, model:map),查找grails-app/views/当前controller/display.gsp;render(view:“ /shared/display”, model:map),查找grails-app/views/shared/display.gsp。
- 文本:render "Hello World!"
- view:render(view:'show')
- Template:render(template:'book_template', collection:Book.list())
- XML:render(text:“some xml", contentType:"text/xml",encoding:"UTF-8")
- HTML片段,由于Grails中Tag可以象方法一样调用,在使用这种方式时,要注意避免跟这些Tag产生名字冲突,导致产生结果无意间调用了Tag。在使用时,应使用全限定名。如:builder.form
render {
builder.form{
for(b in books) {
div(id:b.id, b.title)
}
}
}
- redirect(action:'login')
- redirect(controller:'home',action:'index')
- redirect(uri:"/login.html")
- redirect(action:myaction, params:[p:"v"])
- redirect(action:"next", params:params)
- redirect(controller: "test", action: "show", fragment: "profile"),对应/myapp/test/show#profile
- 在Action转移时,Model被保存
- 后续Action可以访问前一个Action的Model
- chain(action:"a", model:[one:1],params:[p:"v"])
- 访问前一个Action传来的Model,使用chainModel。如:chainModel.one
class ExampleChainController {
def first = {
chain(action:second,model:[one:1])
}
def second = {
chain(action:third,model:[two:2])
}
def third = {
[three:3]
}
}
def beforeInterceptor = { //before返回false,后续action不执行
println "Tracing action ${actionUri}"
}
//入参还可是ModelAndView
def afterInterceptor = { model ->
println "Tracing action ${actionUri}"
}
//auth实现拦截器,except指明拦截器应用的条件
def beforeInterceptor = [action:this.&auth,except:'login']
def auth() {
...
}
def login = {
// display login page
}
- [action:this.&auth,except:'login']
- [action:this.&auth,except:['login','register']]
- [action:this.&auth,only:['secure']]
- 绑定新对象:new Book(params)
- 绑定已有对象:
def b = Book.get(params.id)
b.properties = params
- 方 法1:<g:select name="books" from="${Book.list()}" size="5" multiple="yes" optionKey="id" value="${author?.books}" />,Grails会自动根据select的值来绑定。
- 方法2:如果要更新关联的某些属性,那么就采用:
<g:textField name="books[0].title" value="..." />
<g:textField name="books[1].title" value="..." />Grails 会自动绑定,但是要保证更新顺序和显示顺序的一致性,对于List和Map不存在问题,对于Set要小心。如果显示的textField比实际关联的个数 多,且数组编号连续,如最后加一个“books[2].title”,Grails会自动给关联新增一个实例。如果显示的textField比实际关联的 个数多,且数组编号不连续,如最后加一个“books[5].title”,Grails会自动补齐中间的空缺。本例中会再添加4个:2、3、4、5。
def b = new Book(params['book'])
def a = new Author(params['author'])
- 按类名(通用): typeMismatch.java.net.URL
- 按属性(特殊): typeMismatch.Book.publisherURL
def p = Person.get(1)
p.properties['firstName','lastName'] = params
- params也可使用Map代替
- 排除某属性绑定:bindData(sc, params, [exclude:'prop'])
- 只包含指定属性:bindData(sc, params, [include:'prop'])
def books = Book.list()
//json则为text/json
render(contentType:"text/xml") {
books {
for(b in results) {
book(title:b.title)
}
}
}
render(contentType:"text/json") {
...
}
- 输出简单对象({"hello":"world"}):hello = "world"
- 输出数组({"categories": ["a","b","c"]}):categories = ['a', 'b', 'c']
- 输出对象数组({"categories":[ {"a":"A"} , {"b":"B"}] }):categories = [ { a = "A" }, { b = "B" } ]
- 只输出数组([1,2,3]):
render(contentType:"text/json") {
element 1
element 2
element 3
} - 输出复杂对象({"categories":["a","b","c"],"title":"Hello JSON","information":{"pages":10}}):
render(contentType:"text/json") {
categories = ['a', 'b', 'c']
title ="Hello JSON"
information = {
pages = 10
}
} - 动态输出复杂对象:
def results = Book.list()
render(contentType:"text/json") {
books = array {
for(b in results) {
book title:b.title
}
}
}
def builder = new JSONBuilder()
def result = builder.build {
categories = ['a', 'b', 'c']
title ="Hello JSON"
information = {
pages = 10
}
}
println result.toString()
def sw = new StringWriter()
result.render sw
<g:form action="upload" method="post"
enctype="multipart/form-data">
<input type="file" name="myFile" />
<input type="submit" />
</g:form>
- 直接使用MultipartFile
def f = request.getFile('myFile')
if(!f.empty) {
f.transferTo( new File('/some/local/dir/myfile.txt') )
} - 数据绑定
class Image {
byte[] myFile
}
def img = new Image(params)
- 使用上相当于简版Domain Class(不要误解,Command Object和Domain Class是两回事)。
- 它在Controller目录中定义,一般包含在使用它的Controller文件中,但也可单独抽出。
- 它还可以使用约束,但不能使用那些要查找数据库的约束,如unique。
- 它也支持依赖注入。
class LoginController {
def login = { LoginCommand cmd ->
if(cmd.hasErrors()) {
redirect(action:'loginForm')
}
else {
// do something else
}
}
}
class LoginCommand {
String username
String password
static constraints = {
username(blank:false, minSize:6)
password(blank:false, minSize:6)
}
}
- 前台页面: <g:form useToken="true" ...>
- Controller:
withForm {
// good request
}.invalidToken {
// bad request
} - 如果没有invalidToken,则可通过flash.invalidToken访问
- 注意:withForm需要用到 session,因此,在集群环境下,要设置“session affinity”。这同样也适用于任何使用session的程序
Grails 1.2参考文档速读(10):Controller的更多相关文章
- [转载]正则表达式参考文档 - Regular Expression Syntax Reference.
正则表达式参考文档 - Regular Expression Syntax Reference. [原创文章,转载请保留或注明出处:http://www.regexlab.com/zh/regref. ...
- Spring Boot 2.2.2.RELEASE 版本中文参考文档【3.2 - 3.10】
Spring Boot 2.2.2.RELEASE版本中文文档持续更新中~如有需要获取参考文档文件,关注公众号JavaSo,回复“参考文档”即可. 3.2 结构化代码 Spring Boot不需要任何 ...
- 数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
- Mongoose学习参考文档——基础篇
Mongoose学习参考文档 前言:本学习参考文档仅供参考,如有问题,师请雅正 一.快速通道 1.1 名词解释 Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力 Model ...
- css参考文档; 官方英文说明!! 1 margin padding 百分比参照物 2 margin值为auto时的说明 3 div在div里垂直居中方法 4 dispaly:flex说明
css参考文档 http://css.doyoe.com/ 两篇很好的文章:(下面的css官方英文说明链接 有时间可以研究下 http://www.w3.org/TR/css3-box/ ...
- oracle数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1) 文档内容 用途 详细信息 Patchsets ...
- html5 兼容参考文档 与 浏览器hack兼容参考文档
移动端兼容参考文档 http://mobilehtml5.org/ 浏览器hack http://browserhacks.com/ 附上部分截图
- phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法
phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法 实这个很简单的只要更改php.ini里三个配置即可.(见下面加粗部分,改成你自己的需求即可) ; Maximum allo ...
- CsvHelper文档-2读
CsvHelper文档-2读 这个库默认不需要做任何设置就可以很容易的使用它.如果你的类属性名称直接匹配csv的标题名称,那么可以按照下面的实例来用: (以下所有的代码都需要引用using csvhe ...
随机推荐
- js 定位到指定位置
<script> //滚动定位到product function scroll() { var scroll_offset = $(&quo ...
- Sublime Text 使用 Emmet 补全错误问题
Sublime Text安装了Emmet后,使用Tab或者ctrl+e发现补全有问题,如: div.testClass#testId 变成了 div.<testClass id="te ...
- C#winform初试报表
步骤1.新建一个窗口,拖一个ReportViewer控件上去,设置该控件的Dock为Fill. 步骤2.添加一个报表文件,如:Report1.rdlc,设置其中的参数,这里设置的参数和下面的代码里面的 ...
- js各种宽高(2)
在javascript和jquery中,都有对各种高度的写法,在这里,我们就着重讲一下窗口.文档等高度的理解.(宽度和高度差不多!) jquery的各种高度 首先来说一说$(document)和$(w ...
- Lua 多维表的遍历中的赋值
说到Lua的遍历将要使用到循环:先说遍历再说循环: 遇到这样类似结构的一个table Data={ []={p1=,pa={,,}}, []={p1=,pa={,,}}, []={p1=,pa={,, ...
- PHP Startup: Unable to load dynamic library
昨天帮一朋友配置服务器结果发现apache日志中有PHP Warning: PHP Startup: Unable to load dynamic library 提示了,然后调试数据库连接发现提示C ...
- 【C++】快排
假设要排序的数据类型为int int main() { qsort(a,len,sizeof(int),cmp); //qsort(数组的起始位置,排序个数,类型大小,比较函数); } int cmp ...
- Python基础 第二天
1.http://www.cnblogs.com/beer/p/5672678.html requests和beautifulsoup
- hadoop-cdh with snappy
hadoop: 2.5.0-cdh5.3.6 snappy: 1.1.3 hadoop 2.*不需要hadoop-snappy.只要机器上安装好snappy, 直接编译就可以 编译命令: mvn cl ...
- Fragment+RadioButton实现点击切换页面效果
首先我们需要在主布局文件中 放一个 容器,方便让fragment加入进去,我们创建了四个Fragment,并用RedioButton实现了导航栏 MainActivity.java package c ...