【问题标题】:annotation based Spring bean validation基于注解的 Spring bean 验证
【发布时间】:2008-09-29 16:33:55
【问题描述】:

我正在研究一种使用spring modules 验证Spring bean 的基于注释的方法。在this tutorial 中,使用以下 bean(getter 和 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} 个字符。

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

email=email address is invalid

如果找不到规则的特定于 bean 的消息,则应使用此默认消息。但是,我的经验是,这根本行不通。

另一种避免重复消息的机制是将错误消息的键传递给规则注释。例如,假设我为@Email 规则定义了以下默认错误消息

badEmail=Email address is invalid

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

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

但是我一次又一次地尝试了这个,它似乎不起作用。有没有人在使用此验证框架时找到避免重复错误消息的方法?

【问题讨论】:

    标签: java validation spring-modules


    【解决方案1】:

    我快速浏览了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 是教程中使用的 config 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
    }
    

    【讨论】:

    • 在上面显示的 Spring config 中,configurationLoader bean 是什么?
    • 嗨,Don - 我从您提到的教程网站下载了源代码,并且 configurationLoader 已经是他们的配置 xml 中定义的 bean 之一。当我回到家并查看我编写的代码时,我可以更新此帖子。
    • 本教程中的 configurationLoader bean 的类型为 org.springmodules.validation.bean.conf.loader.annotation.AnnotationBeanValidationConfigurationLoader
    【解决方案2】:

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

    org.springmodules.validation.bean.converter.KeepAsIsErrorCodeConverter

    使用此功能时,将检查资源包是否有以下代码:

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

    • errorCode 是实际的验证错误代码,例如。 not.blank,电子邮件。
    • commandBeanName 与引用 形成支持 bean。
    • fieldName 是字段的名称。
    • fieldClassName 是字段类名称,例如。 java.lang.String, java.lang.Integer

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

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

    如果将errorCode替换为errorCode“badEmail”,如下所示:

    @Email(errorCode="badEmail")

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

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

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

    【讨论】:

      【解决方案3】:

      在您的 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"/>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-27
        • 2010-11-17
        • 1970-01-01
        • 2013-05-14
        • 2018-02-17
        • 1970-01-01
        相关资源
        最近更新 更多