0

我们将以下通用模式用于 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) {
}

我们要求禁止随机查询参数,例如。端点/对象?颜色=蓝色。为此,我们需要访问命令对象中的参数映射,以验证它不包含任何“意外”参数键。据我了解,默认方式只会在名为 color 的 CO 上创建一个成员,我看不出如何防止任意成员使用自定义验证器。我很乐意接受这样做的建议,从而允许我们使用这种默认方式。

4

2 回答 2

1

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

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

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

withValidCommand(cmd) {
     // do work
}

效果很好。但也许你可以想出一些更优雅的东西。

于 2013-09-16T21:28:47.737 回答
0

你应该这样做:

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

通过将 SomeCommandObject 作为参数传入 grails 将自动从 params 填充它并进行验证。无需手动进行。

于 2013-09-16T21:28:32.190 回答