在使用Grails时,你会发现Controller中的Action通常会执行如下三步:获取params中的Id、根据Id获得Domain Class、对Domain Class做一些操作。对于前两步,多个Action都是使用一样的代码,这有悖于DRY原则。Paul Woods根据自己的实践,提出一种模式用以简化这些类似的代码。
方法比较简单。这里以Person为例,首先将获取params中的Id、根据Id获得Domain Class这两步进行封装:
private def withPerson(id="id", Closure c) {
def person = Person.get(params[id])
if(person) {
c.call person
} else {
flash.message = "The person was not found."
redirect action:"list"
}
}
}
之后,在第三步中,使用上述方法,以Update为例:
def update = {
withPerson { person ->
person.properties = params
if(person.validate() && person.save()) {
redirect action:"show", id:person.id
} else {
render view:"edit", model:[person:person]
}
}
}
如果其他的Action,如show、edit、update、delete,也采用这种方法。你会发现检查Domain Class是否存在的代码没了,Controller瘦身了不少,再看看单元测试的代码,亦是如此。
根据这个方法对Controller的template进行修改,则可将这种风格的代码扩展至未来所有的脚手架代码。如下是修改后的部分Controller template:
private def with${className}(id="id", Closure c) {
def ${propertyName} = ${className}.get(params[id])
if(${propertyName}) {
c.call ${propertyName}
} else {
flash.message = "The ${propertyName} was not found."
redirect action:"list"
}
}
def show = {
with${className} { ${propertyName} ->
[${propertyName}: ${propertyName}]
}
}
def edit = {
with${className} { ${propertyName} ->
[${propertyName}: ${propertyName}]
}
}
def update = {
with${className} { ${propertyName} ->
${propertyName} .properties = params
if(${propertyName} .validate() && ${propertyName} .save()) {
redirect action:"show", id:${propertyName}.id
} else {
redirect(action: "list")
}
}
}
def delete = {
with${className} { ${propertyName} ->
try {
${propertyName}.delete(flush:true)
redirect(action: "list")
}catch (org.springframework.dao.DataIntegrityViolationException e) {
redirect(action: "show", id: ${propertyName}.id)
}
}
}
赶快给你的Controller瘦身吧!关于Paul Woods的详细示例代码,请参见原文。

最新评论
9 周 6 小时之前
9 周 1 天之前
11 周 5 天之前
11 周 5 天之前
17 周 2 天之前
17 周 4 天之前
19 周 3 天之前
20 周 1 天之前
20 周 2 天之前
20 周 5 天之前