你的Controller瘦身了么?

在使用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的详细示例代码,请参见原文

By huwh - Posted on 15 九月 2011