如何强制执行Grails命令对象?

时间:2013-09-16 21:15:14

标签: validation grails command-objects

我们对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命名颜色上创建一个成员,我不知道如何使用自定义验证器来防止任意成员。我很乐意接受这样做的建议,从而允许我们使用这种默认方式。

2 个答案:

答案 0 :(得分:1)

是;你可以做的是将命令对象作为参数传递给控制器​​,然后命令将始终自动验证。

此外,您可以做的是制作过滤器或类似过滤器,这样您就不必每次都检查hasErrors(),而是以相同的方式处理所有情况(例如,通过抛出错误,或通过特定回复返回)。

在我们创建的应用程序中,我们有类似的东西:

withValidCommand(cmd) {
     // do work
}

哪个效果很好。但也许你可以提出更优雅的东西。

答案 1 :(得分:0)

你应该这样做:

def someAction(SomeCommandObject co) {
    if (!co.hasErrors()) {
       someService.doWork(co)
    }
}

通过传递SomeCommandObject作为参数,grails将自动从params填充并验证。无需手动完成。