4

Grails 有一个关于数据绑定的错误,当您处理错误的数字输入时,它会引发强制转换异常。JIRA:http: //jira.grails.org/browse/GRAILS-6766

为了解决这个问题,我编写了以下代码来手动处理 POGO 类的数字Foo输入src/groovy

void setPrice(String priceStr)
{
    this.priceString = priceStr

    // Remove $ and , 
    priceStr = priceStr.trim().replaceAll(java.util.regex.Matcher.quoteReplacement('$'),'').replaceAll(',','')

    if (!priceStr.isDouble()) {
        errors.reject(
            'trade.price.invalidformat',
            [priceString] as Object[],
            'Price:[{0}] is an invalid price.')

        errors.rejectValue(
            'price',
            'trade.price.invalidformat')
    } else {
        this.price = priceStr.toDouble();
    }
}

下面就errors.reject()一行抛出空引用异常。

foo.price = "asdf" // throws null reference on errors.reject()
foo.validate()

但是,我可以说:

foo.validate()
foo.price = "asdf" // no Null exception
foo.hasErrors() // false
foo.validate()
foo.hasErrors() // true

validate()调用时错误从何而来?有没有办法在errors不先调用的情况下添加属性validate()

4

3 回答 3

6

我不能确切地告诉你为什么,但你需要显式调用而不是像属性一样getErrors()访问它。errors出于某种原因,Groovy 没有为它调用方法。所以将reject行更改setPrice()

getErrors().reject(
        'trade.price.invalidformat',
        [priceString] as Object[],
        'Price:[{0}] is an invalid price.')

getErrors().rejectValue(
        'price',
        'trade.price.invalidformat')

这是确保Errors对象存在于您的方法中的最简单方法。您可以查看将验证相关方法添加到域类的代码。

于 2013-03-11T22:31:02.387 回答
5

AST 转换处理@Validateable 增加了类,其中包括

  • 一个名为的字段errors
  • 公共方法getErrorssetErrorsclearErrorshasErrors

如果尚未设置该字段,则该getErrors方法会延迟设置该字段。errors所以看起来正在发生的事情是errors在同一个类中的访问被视为字段访问而不是 Java Bean 属性访问,并且绕过了延迟初始化。

所以修复似乎是使用getErrors()而不是仅仅errors.

于 2013-03-11T22:44:07.527 回答
2

这些错误会动态地添加到您的可验证类(域类和具有注释的类@Validateable)中。

允许开发人员设置字符串而不是数字似乎不是一个好方法。此外,您的验证仅适用于该特定类。

我认为更好的方法是为数字注册一个自定义属性编辑器。这是一个带有日期的示例String,它可以将(来自表单)转换为Datedd/MM/yyyy 等格式。这个想法是一样的,因为您将强制您的号码是可解析的(例如,Integer.parseInt()将抛出异常)。

在您的域类中,使用数字类型而不是字符串,因此代码开发人员将不允许存储非数字值。

于 2013-03-11T22:29:32.947 回答