Utilizzando un ResourceBundle personalizzato con Hibernate Validator
-
27-09-2019 - |
Domanda
Sto cercando di creare una fonte di messaggio personalizzato per Hibernate Validator 4.1 attraverso Primavera 3.0. Ho installato la configurazione necessaria:
<!-- JSR-303 -->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource"/>
</bean>
Le traduzioni sono serviti dalla mia sorgente del messaggio, ma sembra che la sostituzione termini nei messaggi stessi sono cercato nella sorgente del messaggio, vale a dire per una:
my.message=the property {prop} is invalid
ci sono richieste di guardare in alto 'prop' nel MessageSource. Entrando in ResourceBundleMessageInterpolator.interpolateMessage
Prendo atto che gli stati javadoc:
Esegue il messaggio di interpolazione secondo algoritmo specificato nella JSR 303.
Nota: Look-up in fasci utente è ricorsivo che, look-up in bundle di default non sono!
Questa mi sembra la ricorsione sarà sempre aver luogo per un bundle specificato dall'utente, così in effetti non riesco a tradurre i messaggi standard, come quello per il formato.
Come faccio a plug-in di mia sorgente del messaggio e in grado di avere i parametri di essere sostituiti nel messaggio?
Soluzione
Questa mi sembra la ricorsione sarà sempre prendere posto per una specificato dall'utente fascio, così in effetti I Non in grado di tradurre i messaggi standard come quella per il formato.
di Hibernate Validator ResourceBundleMessageInterpolator creare due istanze di ResourceBundleLocator (cioè PlatformResourceBundleLocator) uno per messaggi di convalida definito dall'utente - userResourceBundleLocator e l'altro per JSR-303 messaggi di convalida di serie -. DefaultResourceBundleLocator
Qualsiasi testo che appare all'interno di due parentesi graffe esempio {someText}
nel messaggio viene trattato come replacementToken. ResourceBundleMessageInterpolator cerca di trovare il valore corrispondente che può sostituire il replacementToken in ResourceBundleLocators.
- prima in UserDefinedValidationMessages (che è ricorsiva),
- poi in DefaultValidationMessages (che non è ricorsiva).
Quindi, se si mette uno standard JSR-303 messaggio nel dire ResourceBundle personalizzato, validation_erros.properties
, verrà sostituito dal messaggio personalizzato. Si veda a questo ESEMPIO messaggio di convalida standard NotNull 'non può essere null' è stato sostituito da personalizzato messaggio 'MyNotNullMessage'.
Come posso plug-nel mio messaggio fonte e poter avere parametri essere sostituito nel messaggio?
my.message = la proprietà {prop} è non valida
Dopo aver attraversato due ResourceBundleLocators, reperti ResourceBundleMessageInterpolator per più replaceTokens nel resolvedMessage (risolto da entrambi i fasci). Questi replacementToken non sono altro che la nomi degli attributi di annotazione , se tali replaceTokens si trovano nel resolvedMessage, sono sostituiti dai valori del corrispondente annotazione attributi .
ResourceBundleMessageInterpolator.java [Linea 168, 4.1.0.Final]
resolvedMessage = replaceAnnotationAttributes( resolvedMessage, annotationParameters );
Fornire un esempio per sostituire {prop} con valore personalizzato, spero che vi aiuterà a ....
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