使用带有Hibernate Validator的自定义ResourceBundle

Rob*_*anu 12 spring hibernate-validator bean-validation

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

<!-- JSR-303 -->
<bean id="validator"
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationMessageSource" ref="messageSource"/>
 </bean>
Run Code Online (Sandbox Code Playgroud)

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

my.message=the property {prop} is invalid
Run Code Online (Sandbox Code Playgroud)

有人要求在messageSource中查找"prop".进入ResourceBundleMessageInterpolator.interpolateMessage我注意到javadoc说:

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

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

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

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

dir*_*ira 18

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

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

出现在两个大括号内的任何文本(例如{someText}在消息中)都被视为replacementToken.ResourceBundleMessageInterpolator尝试查找可替换ResourceBundleLocators中的replacementToken的匹配值.

  1. 首先在UserDefinedValidationMessages(递归),
  2. 然后在DefaultValidationMessages(这不是递归).

因此,如果您在自定义ResourceBundle中输入标准JSR-303消息validation_erros.properties,它将被您的自定义消息替换.请参阅此示例标准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 );
Run Code Online (Sandbox Code Playgroud)

提供一个用自定义值替换{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 {};
}
Run Code Online (Sandbox Code Playgroud)

MyNotNullValidator.java

public class MyNotNullValidator implements ConstraintValidator<MyNotNull, Object> {
    public void initialize(MyNotNull parameters) {
    }

    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
        return object != null;
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

validation_errors.properties

notNull={propertyName} cannot be null 
Run Code Online (Sandbox Code Playgroud)

测试

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

产量

Custom Message:- userName cannot be null
Run Code Online (Sandbox Code Playgroud)