【问题标题】:Grails command object initializationGrails 命令对象初始化
【发布时间】:2014-05-10 02:13:43
【问题描述】:

在我的 Grails 2.3.8 应用程序中,我定义了以下控制器操作

class RegisterController {

    def register(User user) {
        render text: "User name is '$user.name'"
    }
}

user 参数是域类实例。如果我用 URL 调用这个控制器

http://localhost:8080/myapp/register/register

我收到了NullPointerException。但是我对数据绑定的理解是,如果在没有任何参数的情况下调用此操作,则应为参数分配new User()

【问题讨论】:

  • 不。如果 url 中没有有效的id,则用户域将为空。
  • @dmahapatro 你确定吗?如果这是真的,您似乎永远无法将操作参数与保存新域类实例的操作一起使用
  • @dmahapatro 我不确定这是不是真的。如果您只传递一个与目标对象中的任何字段匹配的表单参数,则会发生数据绑定。
  • @Dónal 我想知道它的行为是否不像命令对象,因为这是一个域类。你可以只用一个命令对象试试看是否得到相同的结果吗?对我来说听起来像是一个错误。我经常使用带有可选/无参数的命令对象来支持模型中的数据。这就是为什么我认为这是一个错误。
  • @JoshuaMoore 你是对的,如果我把它变成一个命令对象,我不会得到异常。我想这是一个 Grails 错误,我已经打开了一张 JIRA 票 jira.grails.org/browse/GRAILS-11393

标签: grails data-binding


【解决方案1】:

但是我对数据绑定的理解是,如果这个动作是 在没有任何参数的情况下调用,应为参数分配一个新的 用户()

不一定是这样。对于域类命令对象,如果不存在参数,则仅为 POST 请求创建一个新实例。

来自http://grails.org/doc/2.4.0.RC1/guide/theWebLayer.html#commandObjects...

如果命令对象的类型是域类并且没有id 请求参数然后 null 将被传递到控制器动作 除非 HTTP 请求方法是“POST”,在这种情况下是一个新实例 将通过调用域类来创建域类的 构造函数。

2.3.8 文档中可能缺少该文本。我会验证并在必要时添加它。

【讨论】:

  • 我已验证注释已针对 2.3.x (github.com/grails/grails-doc/commit/…) 进行了更新。该网站将在下次发布文档时进行更新,以反映该说明,这可能会在下周左右发布 2.3.9。
  • 请注意,此行为在 2.3.8 中发生了变化,因为 jira.grails.org/browse/GRAILS-11247 已得到解决。
  • GRAILS-11247 背后的原因对我来说并不明显,即 why 是当命令是非域类时为 POST 请求创建的新对象,但不是当命令一个域类?
  • 常规命令对象和域类是根本不同的东西。其他命令对象是捆绑和关联请求参数以简化繁琐的控制器代码的便捷方式。域类是由应用程序管理的持久资源。它们根本不是一回事,因此框架如何与它们交互的规则是不同的。与 REST 实践相关的充分理由(但总体上是好主意)解释了为什么按原样处理域类,但这回答了为什么它们不像普通 CO 那样处理的问题。
  • 如果你做对了,如果为所有请求创建了域类,你将不得不在你的控制器操作中放入乏味的代码来弄清楚发生了什么。就像现在一样,URL 映射和 allowedMethods 的组合消除了很多。
【解决方案2】:

如果你修改了怎么办:

'$user.name'

成为:

'${user?.name}'

【讨论】:

  • 那么我显然不会得到 NPE,但这不是我问题的重点
猜你喜欢
  • 1970-01-01
  • 2014-06-07
  • 2013-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多