Grails 命令对象自定义验证消息代码

Posted

技术标签:

【中文标题】Grails 命令对象自定义验证消息代码【英文标题】:Grails Command Objects custom Validate Message Codes 【发布时间】:2013-06-06 14:14:42 【问题描述】:

当使用命令对象时:

class UserCommand 

   String name

   static constraints = 
      name blank: false, unique: true, minSize: 3
   

您可以使用它们来验证对象,而无需使它们持久化。在我的情况下,我将验证持久类用户。

在控制器中:

def save(UserCommand cmd) 
  if(!cmd.validate()) 
      render view: "create", model: [user: cmd]
  return
  
  def user = new User()
  user.name = cmd.name
  user.save()

  redirect uri: '/'

 

在messages.properties中:

user.username.minSize.error=Please enter at least three characters.
userCommand.username.minSize.error=Please enter at least three characters.

使用自定义验证消息时,您必须为每个错误编写两次消息代码。一个用于 User 类,另一个用于 UserCommand 类。

有没有办法让每个错误只有一个消息代码?

【问题讨论】:

这真的是一个直观的问题,让我想如果我可以在UserCommand 的约束中使用属性importFrom User 来实现您所期望的。但不,它不能实现目标。最后,我认为您必须同时提供这两个消息。请参阅Validation and Internationalization,其中特别提到了类名。除非有另一种方法,否则我觉得您必须坚持以上才能在命令对象和域对象中应用验证。继承可能是我持怀疑态度的一个选项。 【参考方案1】:

我在这里可能是错的,但如果您只使用 Grails 约束,共享验证消息的唯一方法是简单地依赖 messages.properties 中的 default.x.x.message 键/值。否则,将通过以下密钥形式查找消息:

className.propertyName.errorcode...=

但是,您可以使用 custom validator 并覆盖为验证错误返回的消息密钥。

class User 
  ...

  static constraints = 
    ...
    name blank: false, unique: true, validator:  value, user ->
      if(!value || value.length() < 3)
        return 'what.ever.key.in.messages.properties'
    
  

然后您可以通过global constraint 或@dmahapatro 提到的在类之间共享约束来保持所有内容干燥,就像这样在您的 UserCommand 中使用importFrom

class UserCommand 
 ...
 static constraints = 
   importFrom User
   ...
  

如果您有更复杂的验证,您可以创建自己的约束类。以下是一些资源:

http://www.zorched.net/2008/01/25/build-a-custom-validator-in-grails-with-a-plugin/ http://blog.swwomm.com/2011/02/custom-grails-constraints.html

【讨论】:

也想到了default 消息,但不想污染默认行为。它可能会影响其他领域。就自定义消息而言,我同意它是灵活的并且可以制作为 DRY,但是对于 OP 所指的所有这些约束,它必须再次完成。比如空白、独特等。对吧?【参考方案2】:
    在 CommandObject 中使用唯一约束没有意义,因为它会检查什么的唯一性? 您可以验证域对象,而无需使用与命令对象完全相同的方式持久化它们 - 使用 validate() 方法

    你可以把一个用户对象放在命令对象中,只为域类设置约束,然后验证用户对象是命令对象的一部分

    class User  
        String name
        static constraints = 
            name blank: false, unique: true, minSize: 3
        
    
    
    class UserCommand 
        User user 
        static constraints = 
            user validator:  it.validate() 
        
    
    
    user.username.minSize.error=Please enter at least three characters.
    

【讨论】:

你打算如何将这个 URL 中的name 绑定到命令对象?http://localhost:8080/myapp/user/save?name=Fo。或者如果从表单提交,您将如何将name 绑定到命令对象? 两种情况,参数/输入名称应该是user.name 所以http://localhost:8080/myapp/user/save?user.name=Fo user.name 对终端客户意味着什么? user是UserCommand类中User对象引用的名称,name是User类中的字段名 是的。为什么该服务的消费者应该知道在服务器端完成的所有这些事情。他/她应该知道我必须在 URL 中发送一个名字。说得通? :)

以上是关于Grails 命令对象自定义验证消息代码的主要内容,如果未能解决你的问题,请参考以下文章

Grails:Spring Security Core 自定义身份验证 getUserByUserName 返回 null 对象

如何注册自定义约束

自定义错误消息的 Grails 问题

Grails 中的自定义验证器中的异常

Grails - Acegi:自定义身份验证方法

Grails:如何使用命令对象验证由项目列表组成的 POST 正文?