我使用的是Spring Boot,Spring JPA,Spring Data REST,Spring HATEOAS,Hibernate验证器。 我创建了自己的约束验证器。
注释:
Target({ java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { TicketBundleValidator.class })
@Documented
public @interface ValidTicketBundle {
String message() default "{server.validators.annotations.ValidTicketBundle.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
验证员:
public class TicketBundleValidator implements ConstraintValidator<ValidTicketBundle, TicketBundle> {
@Override
public void initialize(ValidTicketBundle constraintAnnotation) {
}
@Override
public boolean isValid(TicketBundle value, ConstraintValidatorContext context) {
if (value == null)
return true;
// Must be at least 1 row for each ticket bundle
if (value.getRows().size() == 0)
return false;
// The start/end date must be valid
if (value.getStartDate().isAfter(value.getEndDate()))
return false;
// The sum of payments can't be greater than the total price of the ticket
// bundle
if (value.getTotalPaymentsAmount().compareTo(value.getTotalPrice()) == 1)
return false;
// if ( !isValid ) {
// constraintContext.disableDefaultConstraintViolation();
// constraintContext.buildConstraintViolationWithTemplate(
// "{org.hibernate.validator.referenceguide.chapter06." +
// "constraintvalidatorcontext.CheckCase.message}"
// )
// .addConstraintViolation();
// }
return true;
}
}
我将我的密钥和文本都放在resources / i18n / messages.properties和resources / i18n / validation.properties中:
server.validators.annotations.ValidTicketBundle.message = I dati inseriti non sono validi. Verificare nuovamente e ripetere l'operazione.
我创建了我的测试用例以验证一切是否正常:
@Test
@WithMockUser(roles = "ADMIN")
public void saveTicketBundleWithWrongDateThrowsException() {
TicketBundle ticketBundle = new TicketBundle();
ticketBundle.setCustomer(customer);
ticketBundle.setStartDate(Instant.now().plus(30, ChronoUnit.DAYS));
ticketBundle.setEndDate(Instant.now());
Set<ConstraintViolation<TicketBundle>> constraintViolations = validator.validate(ticketBundle);
assertEquals(1, constraintViolations.size());
ConstraintViolation<TicketBundle> constraintViolation = constraintViolations.iterator().next();
assertEquals("I dati inseriti non sono validi. Verificare nuovamente e ripetere l'operazione.",
constraintViolation.getMessage());
}
但我失败了,因为似乎验证密钥消息未解决:
org.junit.ComparisonFailure: expected:<[I dati inseriti non sono validi. Verificare nuovamente e ripetere l'operazione.]> but was:<[{server.validators.annotations.ValidTicketBundle.message}]>
at org.junit.Assert.assertEquals(Assert.java:115)
我确定我错过了什么,但不清楚是什么。这是一个MVC应用程序,但我不希望REST端点回复带有本地化消息:我希望测试用例也能收到正确的消息。
为了完成图片,我在项目中使用了这个配置类:
@Configuration
@EnableHypermediaSupport(type = { HypermediaType.HAL })
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Bean
public LocaleResolver localeResolver() {
return new SmartLocaleResolver();
}
public class SmartLocaleResolver extends CookieLocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
String acceptLanguage = request.getHeader("Accept-Language");
if (acceptLanguage == null || acceptLanguage.trim().isEmpty()) {
return super.determineDefaultLocale(request);
}
return request.getLocale();
}
}
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/i18n/messages");
// messageSource.setDefaultEncoding("UTF-8");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setCacheSeconds((int) TimeUnit.HOURS.toSeconds(1));
messageSource.setFallbackToSystemLocale(false);
return messageSource;
}
答案 0 :(得分:1)
我在代码中发现了问题。我错了,hibernate验证器将消息字符串查找到根文件夹validationmessages.properties
(https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/?v=6.0#section-message-interpolation)
我在那里设置了消息,一切正常。