我正在使用Hibernate / Validator,Spring Data REST,Spring HATEOAS处理Spring Boot 2.1.4项目。
我重写LocalValidatorFactoryBean以在特定文件夹中定位消息:
@Configuration
@EnableRetry
@EnableTransactionManagement
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class CustomConfiguration {
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:/i18n/messages");
// messageSource.setDefaultEncoding("UTF-8");
// set to true only for debugging
messageSource.setUseCodeAsDefaultMessage(false);
messageSource.setCacheSeconds((int) TimeUnit.HOURS.toSeconds(1));
messageSource.setFallbackToSystemLocale(false);
return messageSource;
}
@Bean
public MessageSourceAccessor messageSourceAccessor() {
return new MessageSourceAccessor(messageSource());
}
/**
* Enable Spring bean validation https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#validation
*
* @return
*/
@Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
factoryBean.setValidationMessageSource(messageSource());
return factoryBean;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
methodValidationPostProcessor.setValidator(validator());
return methodValidationPostProcessor;
}
我还小心地覆盖了getValidator():
@Configuration
@EnableHypermediaSupport(type = {HypermediaType.HAL})
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private LocalValidatorFactoryBean validator;
@Override
public Validator getValidator() {
return validator;
}
我阅读了许多关于此问题的讨论,例如示例https://github.com/spring-projects/spring-boot/issues/3071和相关主题。
我添加了此自定义建议:
/**
* Workaround class for making JSR-303 annotation validation work for controller method parameters. Check the issue
* <a href="https://jira.spring.io/browse/DATAREST-593">DATAREST-593</a>
*/
@ControllerAdvice
public class RequestBodyValidationProcessor extends RequestBodyAdviceAdapter {
@Autowired
private LocalValidatorFactoryBean validator;
@Override
public boolean supports(final MethodParameter methodParameter, final Type targetType,
final Class<? extends HttpMessageConverter<?>> converterType) {
final Annotation[] parameterAnnotations = methodParameter.getParameterAnnotations();
for (final Annotation annotation : parameterAnnotations) {
if (annotation.annotationType().equals(Valid.class)) {
return true;
}
}
return false;
}
@Override
public Object afterBodyRead(final Object body, final HttpInputMessage inputMessage, final MethodParameter parameter,
final Type targetType, final Class<? extends HttpMessageConverter<?>> converterType) {
final Object obj = super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
//TODO Il messaggio come ad esempio {eyeexam.pupillarydistance.missing} non viene interpolato tramite il file di properties
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(obj);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
return obj;
}
}
当我调用rest控制器的端点时,我遇到了缺少的消息解决方法:
@RepositoryRestController
@PreAuthorize("isAuthenticated()")
public class EyeExamController {
@PostMapping(path = "/eyeExams/saveWithNote")
public ResponseEntity<?> save(@Valid @RequestBody EyeExamNote eyeExamNote, Locale locale,
PersistentEntityResourceAssembler resourceAssembler) {
return new ResponseEntity<Resource<?>>(resourceAssembler.toResource(eyeExamService.save(eyeExamNote)), HttpStatus.OK);
}
我希望我的bean的ScriptAsserts验证结果可以正确解析:
@ScriptAssert(lang = "javascript", script = "(_.pupillaryDistanceIntermediate2Tot != null && _.pupillaryDistanceFarTot != null) ? (_.pupillaryDistanceIntermediate2Tot < _.pupillaryDistanceFarTot) :true", alias = "_", reportOn = "pupillaryDistanceIntermediate2Tot", message = "{eyeexam.pupillarydistance.intermediate.lower}"),
相反,当我呼叫端点时,我得到的是字符串{eyeexam.pupillarydistance.intermediate.lower}
作为插值消息而不是文本(根据我的定义,它位于i18n文件夹中的messages.properties文件中)。
有人建议将验证码移到ValidationMessages.properties
中,但这对我不起作用。难道我做错了什么?任何提示表示赞赏。