Grails 控制器(Controllers)
什么是控制器?
一个控制器处理请求并创建或准备返回内容,他可以自己生成返回内容或者委派到一个视图。 创建一个控制器很简单,只需要创建一个以"Controller"结尾的类,并且放到"grails-app/controllers"目录下就可以了。
控制器名字的第一部分被映射到一个URI,同时控制器里定义的每个操作(action)都被映射到一个包含控制器名字的URI。
控制器是一个request-scoped的对象,每次请求都会创建新的实例。.
创建Grails 控制器
I如果你很懒的话,你可以执行"create-controller"这个 target来创建,该命令回提示你输入控制器的名字:
grails create-controller
例如,我们输入 "book" 便会创建以下控制器:
class BookController { ... }
BookController 将映射到 <...>/book 这个URI,注意:grails 并没有在后台做什么特别的事情,他只是通过一个模板来创建一个控制器给你。
创建操作(Actions)
一个控制器可以有多个closure(闭包)属性,每一个都映射到一个URI:
class BookController {
@Property list = {
// do controller logic
// create model
return model
};
}
这个例子将映射到<...>/book/list 这个URI,如果只有一个closure属性,控制器的默认URI将会映射到这个属性上,当然,你可以定义一个名叫"index" 的操作,他会用来处理没有声明操作的URI,如 <...>/book
设置默认的操作
有两种方法来设置默认操作(URI中只有控制器名字的时候执行的操作), 最简单的就是创建一个名叫"index"的操作:
@Property index = {
redirect(action:list)
}
另外,你可以明确的设置 "defaultAction" 属性:
@Property defaultAction = "list"
访问请求参数(request parameter),session等
每个控制器都会有若干属性会在运行时被注入, 这似的你可以访问到请求参数和session等。完整的参考请参见 [动态方法参考]
class BookController {
@Property find = {
def findBy = params["findBy"]
def appContext = servletContext["appContext"]
def loggedUser = session["logged_user"]
// do stuff
// return model
return model
};
}
使用Flash Scope
Flash scope 是在 Rails 中提到的一个概念,其本质是临时储存一些属性给(并且仅给)下一个请求使用,使用过后便被清除掉。这在重定向前需要设置一些信息时非常有用,例如:
@Property delete = {
def b = Book.get( params['id'] )
if(!b) {
flash['message'] = "User not found for id ${params['id']}"
redirect(action:list)
}
... // remaining code
}
将请求数据绑定到Model
请求的参数都是以字符串传递给web应用的, 因此通常我们需要把这些参数转换为他实际上代表的对象。通过Grails 域对象的"properties"属性,这变的很容易 :
@Property save = {
def b = new Book()
b.properties = params
b.save()
}
在上面的例子里,一行代码就可以把请求参数自动的、神奇的转换并设置到Book的实例里。如果你使用一个别的自定义对象,你可以使用控制器提供的"bindData" 方法:
def sc = new SaveCommand()
bindData(sc, params)
返回Model
一个model实际上是一个在渲染视图时需要的一个map,有很多种方法来返回一个model,第一种就是显式的返回一个map实例:
@Property show = {
def b = Book.get( params['id'] )
return [ book : b ]
}
如果没有显式的返回一个model实例,控制器上的属性将被作为model使用,因此你可以这么写:
class BookController {
@Property List books
@Property List authors
@Property list = {
books = Book.list()
authors = Author.list()
}
}
在这里"books" 和"authors" 这两个属性将可以在视图渲染时使用,更复杂的一种做法是直接返回一个 Spring ModelAndView 类的实例.
渲染返回内容
有时候这很简单 (特别是在Ajax 应用里) ,只需要在控制器里直接返回文本或者代码就可以了。使用相当灵活的 "render" 方法:
render "Hello World!"
这个例子直接使用 "Hello World!" 作为返回内容,再给一个例子:
// write some markup render { for(b in books) { div(id:b.id, b.title) } } // render a specific view render(view:'show') // render a template for each item in a collection render(template:'book_template', collection:B