我们对Grails控制器和命令对象使用以下一般模式
SomeController {
def someAction() {
SomeCommandObject co = SomeCommandObject.valueOf(params)
if(!co.validate()) {
// return bad request
}
someService.doWork(co)
// return ok
}
SomeService {
def doWork(SomeCommandObject co) {
notTrue(!co.hasErrors(), 'cant have errors') // Commons validation
// do actual work
}
}
显然,如果没有调用co.validate(),则.hasErrors()将始终返回false。是否有更好的方法来强制执行.validate()在应用程序层之间传递命令对象之前已经调用过?我们不想传递无效的命令对象,但我们也不想强制每个新方法重新验证命令对象。
注意:我们没有使用默认的控制器/命令对象创建模式,因为我们需要做一些自定义参数映射检查,我们使用静态valueOf方法来创建命令对象。也欢迎改变这种做法的答案。
编辑:关于我们为什么不使用“默认”控制器/命令对象创建的更多信息。特别是为什么我们不这样做..
def someAction(SomeCommandObject co) {
}
我们要求禁止随机查询参数,例如。端点/对象?颜色=蓝色。为此,我们需要访问命令对象中的参数映射,以验证它不包含任何“意外”参数键。据我了解,默认方式只是在CO命名颜色上创建一个成员,我不知道如何使用自定义验证器来防止任意成员。我很乐意接受这样做的建议,从而允许我们使用这种默认方式。
答案 0 :(得分:1)
是;你可以做的是将命令对象作为参数传递给控制器,然后命令将始终自动验证。
此外,您可以做的是制作过滤器或类似过滤器,这样您就不必每次都检查hasErrors(),而是以相同的方式处理所有情况(例如,通过抛出错误,或通过特定回复返回)。
在我们创建的应用程序中,我们有类似的东西:
withValidCommand(cmd) {
// do work
}
哪个效果很好。但也许你可以提出更优雅的东西。
答案 1 :(得分:0)
你应该这样做:
def someAction(SomeCommandObject co) {
if (!co.hasErrors()) {
someService.doWork(co)
}
}
通过传递SomeCommandObject作为参数,grails将自动从params填充并验证。无需手动完成。