Spring 验证 ConstraintViolationException 无法使用 ControllerAdvice 捕获

klc*_*klc 5 spring-mvc

我正在使用 spring Rest 构建 API 并尝试验证输入参数,如下所示:

@RequestMapping("/myUrl")
@RestController
@Validated
public class MyController {

  @ResponseStatus(HttpStatus.OK)
  @RequestMapping(value = "getSomething", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE})
  public myResponse getMarketResult(
  @RequestParam @NotNull @NotBlank @NotEmpty String inputParam) {
    //...my implementation
  }
}
Run Code Online (Sandbox Code Playgroud)

验证确实适用于所有这些场景(空、空白、空)。如果为 null,则抛出 MissingServletRequestParameterException;如果为空白/空,则抛出 ConstraintViolationException。

控制器建议:

@ControllerAdvice
public class ControllerValidationHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler(NestedServletException.class)
  public ResponseEntity<Object> processValidationError(NestedServletException ex, HttpStatus status, WebRequest request) {
    // my implementation
  }

  @ExceptionHandler(ConstraintViolationException.class)
  public ResponseEntity<Object> processValidationError(ConstraintViolationException ex, HttpStatus status, WebRequest request) {
    // my implementation
  }

  @Override
  protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
    // my implementation
  }

  @ExceptionHandler(Exception.class)
  public ResponseEntity<Object> handleExpception(HttpServletRequest req, Exception ex, WebRequest request) {
    // my implementation
  }
Run Code Online (Sandbox Code Playgroud)

然而我观察到:

  1. ConstraintViolationException 作为 org.springframework.web.util.NestedServletException 的原因被抛出。

  2. ControllerAdvice 无法捕获 ConstraintViolationException 和 NestedServletException (但 MissingServletRequestParameterException 有效),它现在返回 html (而不是 json)。

这两个异常也不会被 ResponseEntityExceptionHandler 的“handleException”处理。

问题1和问题2如何解决?我使用的是 Spring 版本 4.3.1

编辑1:再举一个例子,如果我有这样的参数:

@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) @NotNull LocalDate localDate
Run Code Online (Sandbox Code Playgroud)

当请求为空时(例如 '/myURL/getSomething?localDate='