基于注释的Spring bean验证

时间:2008-09-29 16:33:55

标签: java validation spring-modules

我正在调查使用spring modules验证Spring bean的基于注释的方法。在this tutorial中,以下bean(省略了getters和setter)用作示例:

public final class User {  

  @NotBlank  
  @Length(max = 80)  
  private String name;  

  @NotBlank  
  @Email  
  @Length(max = 80)  
  private String email;  

  @NotBlank  
  @Length(max = 4000)  
  private String text;  
}

如果违反特定验证规则,则使用的错误消息应遵循以下格式:

bean-class.bean-propery[validation-rule]=Validation Error message

上面显示的类的示例包括:

User.email[not.blank]=Please enter your e-mail address.  
User.email[email]=Please enter a valid e-mail address.  
User.email[length]=Please enter no more than {2} characters.

消息键包含类名的事实存在一些问题:

  1. 如果重命名了类,则还需要更改消息键
  2. 如果我有另一个类(例如Person),其电子邮件属性的验证与User.email相同,我需要复制这些邮件,例如

    Person.email [not.blank] =请输入您的电子邮件地址 Person.email [email] =请输入有效的电子邮件地址 Person.email [length] =请输入不超过{2}个字符。

  3. 事实上,文档声称可以为特定规则(例如@Email)配置默认消息,如下所示:

    email=email address is invalid
    

    如果找不到规则的特定于bean的消息,则应使用此缺省消息。但是,我的经验是,这根本不起作用。

    避免重复消息的另一种机制是将错误消息的密钥传递给规则注释。例如,假设我已为@Email规则

    定义了以下默认错误消息
    badEmail=Email address is invalid
    

    如果我注释相关属性,则应使用此消息:

    @Email(errorCode="badEmail")
    private String email;
    

    然而,我一次又一次地试了这个,它似乎没有用。有没有人找到一种方法来避免在使用此验证框架时重复错误消息?

3 个答案:

答案 0 :(得分:6)

我快速查看了BeanValidator API,看起来您可能想要尝试 errorCodeConverter 属性。

您需要实现自己的ErrorCodeConverter,还是使用其中一个提供的实现?

....
<bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
    p:configurationLoader-ref="configurationLoader"
    p:errorCodeConverter-ref="errorCodeConverter" />

<bean id="errorCodeConverter" class="contact.MyErrorCodeConverter" />
....

注意:configurationLoader是在教程中使用的配置XML中定义的另一个bean

示例转换器:

package contact;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springmodules.validation.bean.converter.ErrorCodeConverter;

public class MyErrorCodeConverter implements ErrorCodeConverter {

    private Log log = LogFactory.getLog(MyErrorCodeConverter.class);

    @Override
    public String convertPropertyErrorCode(String errorCode, Class clazz, String property) {
        log.error(String.format("Property %s %s %s", errorCode, clazz.getClass().getName(), property));
        return errorCode;  // <------ use the errorCode only
    }

    @Override
    public String convertGlobalErrorCode(String errorCode, Class clazz) {
        log.error(String.format("Global %s %s", errorCode, clazz.getClass().getName()));
        return errorCode;
    }
}

现在属性应该有效:

MyEmailErrorCode=Bad email

class Foo {
    @Email(errorCode="MyEmailErrorCode")
    String email
}

答案 1 :(得分:2)

Spring验证确实有一个ErrorCodeConverter来执行此操作:

org.springmodules.validation.bean.converter.KeepAsIsErrorCodeConverter

使用此选项时,将检查资源包以查找以下代码:

[errorCode.commandBeanName.fieldName,errorCode.fieldName,errorCode.fieldClassName,errorCode]

  • errorCode是实际的验证errorCode,例如。 not.blank,电子邮件。
  • commandBeanName与引用该模型的模型键名称相同 形成支持豆。
  • fieldName是字段的名称。
  • fieldClassName是字段类名称,例如。 java.lang.String,java.lang.Integer

例如,如果我有一个通过键&#34; formBean&#34;在模型中引用的bean。并且java.lang.String类型的字段emailAddress不包含电子邮件地址,这会导致errorCode电子邮件。验证框架将尝试解析以下消息代码:

[email.formBean.emailAddress,email.emailAddress,email.java.lang.String,email]

如果将errorCode替换为errorCode&#34; badEmail&#34;像这样:

@Email(错误码=&#34; badEmail&#34)

框架将尝试解析的消息代码为:

[badEmail.formBean.emailAddress,badEmail.emailAddress,badEmail.java.lang.String,badEmail]

我建议保持errodCode相同。因此,一条消息可用于具有与之关联的errorCode的所有字段。如果您需要更具体地显示某个字段的消息,可以使用代码errorCode.commandBeanName.field向资源包添加消息。

答案 2 :(得分:0)

applicationContext.xml文件中添加以下bean。

<bean id="configurationLoader"
    class="org.springmodules.validation.bean.conf.loader.annotation.AnnotationBeanValidationConfigurationLoader" />

<!-- Use the error codes as is. Don't convert them to <Bean class name>.<bean field being validated>[errorCode]. -->    
<bean id="errorCodeConverter"
    class="org.springmodules.validation.bean.converter.KeepAsIsErrorCodeConverter"/>

 <!-- shortCircuitFieldValidation = true ==> If the first rule fails on a field, no need to check 
    other rules for that field -->   
<bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
    p:configurationLoader-ref="configurationLoader"
    p:shortCircuitFieldValidation="true" 
    p:errorCodeConverter-ref="errorCodeConverter"/>