使用带有Hibernate Validator的自定义ResourceBundle

时间:2010-11-23 16:28:46

标签: spring bean-validation hibernate-validator

我试图通过Spring 3.0为Hibernate Validator 4.1设置自定义消息源。我已经设置了必要的配置:

<!-- JSR-303 -->
<bean id="validator"
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationMessageSource" ref="messageSource"/>
 </bean>

翻译是从我的消息来源提供的,但似乎在消息来源中查找消息本身中的替换令牌,即:a /:

my.message=the property {prop} is invalid

有电话要求查找&#39; prop&#39;在messageSource中。进入ResourceBundleMessageInterpolator.interpolateMessage我注意到javadoc声明:

  

根据JSR 303中指定的算法运行消息插值。

     

注意:   用户捆绑包中的查找是递归的,而默认捆绑包中的查找不是!

在我看来,对于用户指定的包总是会发生递归,所以实际上我无法翻译像Size这样的标准消息。

如何插入我自己的消息源并能够在消息中替换参数?

1 个答案:

答案 0 :(得分:18)

  

这就像递归一样   将永远发生在一个   用户指定的包,所以实际上我   无法翻译标准消息   就像大小一样。

Hibernate Validator的ResourceBundleMessageInterpolator创建两个ResourceBundleLocator实例(即PlatformResourceBundleLocator),一个用于UserDefined验证消息 - userResourceBundleLocator,另一个用于JSR-303标准验证消息 - defaultResourceBundleLocator。

出现在两个大括号内的任何文字,例如邮件中的{someText}被视为replacementToken。 ResourceBundleMessageInterpolator尝试查找匹配值,该值可替换ResourceBundleLocators中的replacementToken。

  1. 首先在UserDefinedValidationMessages(递归)中,
  2. 然后在DefaultValidationMessages中(不是递归的)。
  3. 因此,如果您在自定义ResourceBundle中添加标准JSR-303消息validation_erros.properties,它将被您的自定义消息替换。请参阅此EXAMPLE标准NotNull验证消息'可能不为空'已被自定义'MyNotNullMessage'消息替换。

      
        

    如何插入我自己的信息     源和能够有参数     在消息中被替换?
        my.message =属性{prop}是     无效

      

    在浏览了两个ResourceBundleLocators之后,ResourceBundleMessageInterpolator在resolvedMessage中找到更多的replaceTokens(由两个bundle解析)。这些replacementToken只是Annotation属性的名称,如果在resolvedMessage中找到了这样的replaceTokens,它们将被匹配的Annotation属性的值替换

    ResourceBundleMessageInterpolator.java [第168行,4.1.0.Final]

    resolvedMessage = replaceAnnotationAttributes( resolvedMessage, annotationParameters );
    

    提供一个用自定义值替换{prop}的示例,我希望它能帮到你......

    <强> MyNotNull.java

    @Constraint(validatedBy = {MyNotNullValidator.class})
    public @interface MyNotNull {
        String propertyName(); //Annotation Attribute Name
        String message() default "{myNotNull}";
        Class<?>[] groups() default { };
        Class<? extends Payload>[] payload() default {};
    }
    

    <强> MyNotNullValidator.java

    public class MyNotNullValidator implements ConstraintValidator<MyNotNull, Object> {
        public void initialize(MyNotNull parameters) {
        }
    
        public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
            return object != null;
        }
    }
    

    <强> User.java

    class User {
        private String userName;
    
        /* whatever name you provide as propertyName will replace {propertyName} in resource bundle */
       // Annotation Attribute Value 
        @MyNotNull(propertyName="userName") 
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
    }
    

    <强> validation_errors.properties

    notNull={propertyName} cannot be null 
    

    <强>测试

    public void test() {
        LocalValidatorFactoryBean factory = applicationContext.getBean("validator", LocalValidatorFactoryBean.class);
        Validator validator = factory.getValidator();
        User user = new User("James", "Bond");
        user.setUserName(null);
        Set<ConstraintViolation<User>> violations = validator.validate(user);
        for(ConstraintViolation<User> violation : violations) {
            System.out.println("Custom Message:- " + violation.getMessage());
        }
    }
    

    <强>输出

    Custom Message:- userName cannot be null