2008-09-29 137 views
14

我正在研究基于注释的方法来验证Spring beans,使用spring modules。在this tutorial,以下豆(省略getter和setter)被用作例如:基于注释的Spring bean验证

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; 

不过,我想这一点,一次又一次,它似乎并没有工作。有没有人找到一种方法来避免使用此验证框架时重复错误消息?

回答

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 
} 
+0

在上面显示的Spring配置中,什么是configurationLoader bean? – 2008-10-07 15:33:08

2

Spring验证确实有一个ErrorCod eConverter,这是否:

org.springmodules.validation.bean.converter.KeepAsIsErrorCodeConverter

当这样使用时,资源束将被检查为以下代码:

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

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

因此,举例来说,如果我有一个是在模型的关键“的formBean”和java.lang.String类型的字段EMAILADDRESS引用的Bean不包含一个电子邮件地址,它会导致errorCode电子邮件。验证框架将尝试解决以下消息代码:

[email.formBean.emailAddress,email.emailAddress,email.java.lang.String,电子邮件]

如果错误码为用的errorCode改为“ badEmail”是这样的:

@Email(错误码= “badEmail”)

中的消息代码,该框架将试图解决将是:

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

我建议保持errodCode相同。因此,一条消息可以用于具有与它们相关的errorCode的所有字段。如果您需要针对特定​​字段的消息更加具体,则可以使用代码errorCode.commandBeanName.field将消息添加到资源包中。

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"/>