JSR - Spring @RestController 和 Spring Boot 的 349 bean 验证

JSR - 349 bean validation for Spring @RestController with Spring Boot

我正在使用 Spring Boot 1.5.2.RELEASE 并且无法在方法本身为 @RequestParam@PathVariable 合并 JSR-349(bean 验证 1.1)。

对于 POST 请求,如果方法参数是 Java POJO,则使用 @Valid 注释该参数工作正常,但注释 @RequestParam & @PathVariable @NotEmpty@Email 之类的东西不起作用。

我已经用 Spring 的 @Validated

注释了控制器 class

关于 SO 有很多问题,我在 this answer 上评论说它对我不起作用。

Spring 引导包括 - validation-api-1.1.0.Final.jarhibernate-validator-5.3.4.Final.jar

我错过了什么吗?

示例代码,

@RequestMapping(method = RequestMethod.GET, value = "/testValidated", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseBean<String> testValidated(@Email @NotEmpty @RequestParam("email") String email) {
    ResponseBean<String> response = new ResponseBean<>();
    response.setResponse(Constants.SUCCESS);
    response.setMessage("testValidated");
    logger.error("Validator Not called");
    return response; 
}

当我为 email 发送空值或格式不正确的电子邮件地址时,永远不会调用下面的处理程序,并且控制总是转到 testValidated 方法中。

@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseBean handle(ConstraintViolationException exception) {

    StringBuilder messages = new StringBuilder();
    ResponseBean response = new ResponseBean();

    exception.getConstraintViolations().forEach(entry -> messages.append(entry.getMessage() + "\n"));

    response.setResponse(Constants.FAILURE);
    response.setErrorcode(Constants.ERROR_CODE_BAD_REQUEST);
    response.setMessage(messages.toString());
    return response;
}

ResponseBean<T> 是我的特定应用 class。

经过两天多的点击和试用失败后,我才提出这个问题。由于围绕 Spring 验证和 JSR 验证、Spring 如何调用 JSR 验证器、JSR 标准的更改以及支持的验证类型的混淆,因此存在许多令人困惑的答案。

最后,this article帮了大忙。

我分两步解决了问题,

1.Added 跟随 bean 到我的 Configuration - 没有这些 bean,什么都行不通。

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
    MethodValidationPostProcessor mvProcessor = new MethodValidationPostProcessor();
    mvProcessor.setValidator(validator());
    return mvProcessor;
}           

@Bean
public LocalValidatorFactoryBean validator() {
    LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
    validator.setProviderClass(HibernateValidator.class);
    validator.afterPropertiesSet();
    return validator;
}

2.Placed Spring 在我的控制器上的 @Validated 注释如下所示,

@RestController
@RequestMapping("/...")
@Validated
public class MyRestController {
}

验证为 - org.springframework.validation.annotation.Validated

此设置不影响同一控制器中 @RequestBody 验证的 @Valid 注释,并且这些注释继续按原样工作。

现在,我可以为 MyRestController class、

中的方法触发验证,如下所示
@RequestMapping(method = RequestMethod.GET, value = "/testValidated" , consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseBean<String> testValidated(
        @Email(message="email RequestParam is not a valid email address") 
        @NotEmpty(message="email RequestParam is empty") 
        @RequestParam("email") String email) {
    ResponseBean<String> response = new ResponseBean<>();
    ....
    return response; 
}

我必须在异常处理程序中为异常添加另一个处理程序 - ConstraintViolationException 尽管因为 @Validated 抛出此异常而 @Valid 抛出 MethodArgumentNotValidException

Spring 添加@Validated 时@Validated @Controller 没有映射。从控制器本身移除任何继承确实有帮助。否则 Sabir Khan 的回答有效并且确实有帮助。