我正在寻找如何清理我的Grails控制器代码的方法。在各种控制器中,我或多或少都有相同的逻辑。
是否有建议的方法使控制器操作重用公共代码?
---解决方案---
该问题的所有答案都有助于我们实施的解决方案。
我们使用Mixin方法创建了一个在控制器中使用的类。 mixin公开的方法之一是withObject方法。此方法从控制器获取域名,并使用此方法作为基础。当然可以覆盖此行为!
def withObject(object=this.getClass().getName()-"Controller", id="id", Closure c) {
assert object
def obj = grailsApplication.classLoader.loadClass(object).get(params[id])
if(obj) {
c.call obj
} else {
flash.message = "The object was not found"
redirect action: "list"
}
}
所以所有答案都有助于解决方案!非常感谢!
答案 0 :(得分:8)
当这个问题出现时,我总是拿出这篇博文:
http://mrpaulwoods.wordpress.com/2011/01/23/a-pattern-to-simplify-grails-controllers/
基本上,您的控制器中有各种域的私人帮助程序。
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"
}
}
你对getter进行编码的方式非常灵活,对我来说一个典型的用途(博客中没有涉及)是用于编辑等。
我通常以这种方式编码(我喜欢它清晰划分和可读性的模式):
def editIssue() {
withIssue { Issue issue ->
def issueTypes = IssueTypeEnum.values().collect {it.text }
[issueTypes:issueTypes,activePage:"issue", issue: issue]
}
}
def doEditIssue(IssueCommand cmd) {
if(cmd.validate()) {
withIssue { Issue issue ->
issue.updateIssue(cmd)
redirect(action: "show", id: issue.id)
}
}
else {
def issueTypes = IssueTypeEnum.values().collect {it.text }
render(view: "edit", model:[issueTypes:issueTypes,issue:cmd,activePage:"issue"])
}
}
我的getter助手是:
private def withIssue( Closure c) {
def issue = Issue.get(params.id)
if(issue) {
c.call issue
}
else {
response.sendError(404)
}
}
我认为mixin方法(非常类似于'扩展常见的抽象控制器'方式)也很好,但这种方式有两个好处:
在我绑定到edit()的视图中,我只是在id="${issue.id}"
中添加<g:form>
,它可以无缝地工作。
答案 1 :(得分:6)
我不建议继承,因为你不能在几个超类中传播泛型方法。如果你有很多控制器,你的抽象类会很快变得混乱。您无法使用合成(例如使用服务),因为您无法直接访问response
,render
或params
。
我使用的方法是通过Mixins注入泛型方法。
@Mixin(ControllerGenericActions)
@Mixin(ControllerUtil)
class BookController {
def show = &genericShow.curry(Book)
def exists = {
render(idExists(Book))
}
}
第一个操作show
在ControllerGenericActions.groovy
中使用了一个通用方法,并将一个参数绑定到它。 mixin idExists
方法的第二种用法是在控制器操作中。
以下是src/groovy/ControllerGenericActions.groovy
class ControllerGeneric {
def genericShow(Class clazz) {
render clazz.get(params.id) as XML
}
}
并在src/groovy/ControllerUtil.groovy
class ControllerUtil {
def idExists (Class clazz) {
return clazz.get(params.id) != null
}
在这种情况下不是很有用,但你明白了。
答案 2 :(得分:0)
使用常用方法实现抽象控制器(使用'protected'指令)并从中扩展您的真实控制器。不要在此方法名称的开头使用“get”和“set”字样。不好,但它有效。