복붙노트

[SPRING] Hibernate Validator와 함께 커스텀 ResourceBundle 사용하기

SPRING

Hibernate Validator와 함께 커스텀 ResourceBundle 사용하기

Spring 3.0을 통해 Hibernate Validator 4.1에 대한 커스텀 메시지 소스를 설정하려고한다. 필요한 구성을 설정했습니다.

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

번역본은 내 메시지 소스에서 제공되지만 메시지 소스의 대체 토큰은 다음과 같이 메시지 소스에서 조회됩니다.

my.message=the property {prop} is invalid

messageSource에서 'prop'를 검색하는 호출이있다. ResourceBundleMessageInterpolator.interpolateMessage에 들어가면 javadoc에서 다음과 같은 내용을 나타냅니다.

이것은 재귀가 항상 사용자 지정 번들에서 발생하는 것처럼 보이기 때문에 사실상 크기와 같은 표준 메시지를 변환 할 수 없습니다.

내 메시지 소스를 플러그인하고 메시지에서 매개 변수를 대체 할 수 있습니까?

해결법

  1. ==============================

    1.Hibernate Validator의 ResourceBundleMessageInterpolator는 UserDefined 검증 메시지를위한 ResourceBundleLocator (즉, PlatformResourceBundleLocator)의 두 개의 인스턴스를 생성한다. userResourceBundleLocator와 JSR-303 표준 유효성 검사 메시지에 대한 다른 하나는 defaultResourceBundleLocator이다.

    Hibernate Validator의 ResourceBundleMessageInterpolator는 UserDefined 검증 메시지를위한 ResourceBundleLocator (즉, PlatformResourceBundleLocator)의 두 개의 인스턴스를 생성한다. userResourceBundleLocator와 JSR-303 표준 유효성 검사 메시지에 대한 다른 하나는 defaultResourceBundleLocator이다.

    두 개의 중괄호 안에 표시되는 텍스트 (예 : 메시지의 {someText}는 replacementToken으로 처리됩니다. ResourceBundleMessageInterpolator는 ResourceBundleLocators 내의 replacementToken를 옮겨 놓을 수있는 값을 찾아냅니다.

    따라서 표준 JSR-303 메시지를 사용자 정의 ResourceBundle, 즉 validation_erros.properties에 넣으면 사용자 정의 메시지로 바뀝니다. 이 예제에서 참조 표준 NotNull 유효성 검사 메시지 'null이 아닐 수도 있습니다'가 사용자 지정 'MyNotNullMessage'메시지로 대체되었습니다.

    두 ResourceBundleLocators를 모두 살펴본 후 ResourceBundleMessageInterpolator는 resolvedMessage에서 두 번들로 해결되는 replaceTokens를 더 찾습니다. 이러한 replacementToken는 Annotation 속성의 이름 일 뿐이며, 해당 replaceTokens가 resolvedMessage에 있으면 일치하는 Annotation 속성 값으로 바뀝니다.

    ResourceBundleMessageInterpolator.java [줄 168, 4.1.0. 최종]

    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
    
  2. from https://stackoverflow.com/questions/4258314/using-a-custom-resourcebundle-with-hibernate-validator by cc-by-sa and MIT license