12

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 に次のように記載されていることに注意してください。

JSR 303 で指定されたアルゴリズムに従ってメッセージ補間を実行します。

注: ユーザー バンドルのルックアップは再帰的ですが、デフォルト バンドルのルックアップは再帰的ではありません!

これは、ユーザー指定のバンドルに対して常に再帰が行われるように見えるため、実際にはサイズのような標準メッセージを翻訳できません。

独自のメッセージ ソースをプラグインして、メッセージ内のパラメーターを置き換えるにはどうすればよいですか?

4

1 に答える 1

18

これは、ユーザー指定のバンドルに対して常に再帰が行われるように見えるため、実際にはサイズのような標準メッセージを翻訳できません。

Hibernate Validator の ResourceBundleMessageInterpolator は、ResourceBundleLocator (つまり、PlatformResourceBundleLocator) の 2 つのインスタンスを作成します。1 つは UserDefined 検証メッセージ用 - userResourceBundleLocator で、もう 1 つは JSR-303 標準検証メッセージ - defaultResourceBundleLocator 用です。

メッセージなど、 2 つの中かっこ内に表示されるテキストはすべて{someText}、replacementToken として扱われます。ResourceBundleMessageInterpolator は、ResourceBundleLocators の replacementToken を置き換えることができる一致する値を見つけようとします。

  1. 最初に UserDefinedValidationMessages (再帰的) で、
  2. 次に DefaultValidationMessages (再帰的ではありません)。

したがって、標準の JSR-303 メッセージをカスタム ResourceBundle に入れると、validation_erros.propertiesカスタム メッセージに置き換えられます。このを参照してください。標準の NotNull 検証メッセージ「null ではない可能性があります」は、カスタムの「MyNotNullMessage」メッセージに置き換えられました。

独自のメッセージ ソースをプラグインして、メッセージ内のパラメーターを置き換えるにはどうすればよいですか?
my.message=プロパティ {prop} は無効です

両方の ResourceBundleLocators を通過した後、ResourceBundleMessageInterpolator は、resolvedMessage (両方のバンドルによって解決された) でさらに多くの replaceTokens を見つけます。これらの replacementToken はアノテーションの属性の名前にすぎません。そのような replaceToken が resolveMessage で見つかった場合、それらは一致するアノテーションの属性の値に置き換えられます。

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;
    }
}

ユーザー.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
于 2010-11-23T20:53:32.193 に答える