Verwenden einer benutzerdefinierten Resource mit Hibernate Validator
-
27-09-2019 - |
Frage
Ich versuche, eine benutzerdefinierte Nachrichtenquelle für Hibernate Validator 4.1 bis Frühjahr 3.0 einzurichten. Ich habe die notwendige Konfiguration einrichten:
<!-- JSR-303 -->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource"/>
</bean>
Die Übersetzungen werden von meiner Nachrichtenquelle gedient, aber es scheint, dass die Ersatz-Token in den Nachrichten selbst werden in der Nachrichtenquelle nachgeschlagen, das heißt für ein:
my.message=the property {prop} is invalid
Es gibt Anrufe ‚prop‘ in der Message nachzuschlagen. Going in ResourceBundleMessageInterpolator.interpolateMessage
ich stelle fest, dass die javadoc heißt es:
Führt die Nachricht Interpolation nach Algorithmus angegeben in JSR 303.
Hinweis: Look-ups in Benutzerbündel ist rekursiv während Look-ups in Standard-Bundle sind nicht!
Das sieht für mich wie die Rekursion stattfinden wird immer für ein vom Benutzer festgelegten Bündel, so in der Tat kann ich übersetze nicht-Standard-Nachrichten wie die für Größe.
Wie kann ich meine eigenen Nachrichtenquelle Plug-in und in der Lage sein, Parameter in der Nachricht ersetzt werden sollen?
Lösung
Das sieht für mich wie die Rekursion stattfinden wird immer für ein Benutzer angegebenen Bündel, so in der Tat I kann nicht Standard-Nachrichten übersetzen wie die für Größe.
Hibernate Validator des ResourceBundleMessageInterpolator erstellen zwei Instanzen von ResourceBundleLocator (d PlatformResourceBundleLocator) eine für UserDefined Validierungsmeldungen - userResourceBundleLocator und die andere für JSR-303 Standard-Validierungsmeldungen -. DefaultResourceBundleLocator
Jeder Text, erscheint innerhalb von zwei geschweifte Klammern z.B. {someText}
in der Nachricht wird als replacementToken behandelt. ResourceBundleMessageInterpolator versucht, den passenden Wert zu finden, die die replacementToken in ResourceBundleLocators ersetzen kann.
- zuerst in UserDefinedValidationMessages (die rekursiv),
- dann in DefaultValidationMessages (nicht rekursiv).
Wenn Sie also eine Standard-JSR-303-Nachricht in benutzerdefinierten Resource sagen wir setzen, validation_erros.properties
, wird es durch Ihre kundenspezifische Mitteilung ersetzt werden. Sehen Sie in diesem Beispiel Standard-NotNull Validierungsnachricht ‚nicht null sein‘ hat ersetzt durch custom 'MyNotNullMessage' Nachricht.
Wie kann ich Plug-in meiner eigenen Nachricht Quelle und der Lage sein, Parameter zu haben, wird in der Nachricht ersetzt?
my.message = die Eigenschaft {prop} ist ungültig
Nachdem beide ResourceBundleLocators durchlaufen, ResourceBundleMessageInterpolator Funde für mehr replaceTokens im resolvedMessage (von beiden Bündel aufgelöst). Diese replacementToken sind nichts anderes als die Namen der Annotation Attribute , wenn eine solche replaceTokens im resolvedMessage gefunden werden, werden sie durch die Werte der Anpassungs Annotation ersetzt Attribute .
ResourceBundleMessageInterpolator.java [Zeile 168, 4.1.0.Final]
resolvedMessage = replaceAnnotationAttributes( resolvedMessage, annotationParameters );
Die Bereitstellung eines Beispiels zu ersetzen {prop} mit benutzerdefinierten Wert, ich hoffe, es wird Ihnen helfen ....
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
Test
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());
}
}
Output
Custom Message:- userName cannot be null