Spring Boot 2.1验证消息解析在@RepositoryRestController

时间:2019-04-18 13:42:28

标签: spring spring-boot spring-mvc hibernate-validator spring-validator

我正在使用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中,但这对我不起作用。难道我做错了什么?任何提示表示赞赏。

0 个答案:

没有答案