Java 如何在响应正文中返回ConstraintViolationException消息?

Java 如何在响应正文中返回ConstraintViolationException消息?,java,spring,spring-boot,annotations,bean-validation,Java,Spring,Spring Boot,Annotations,Bean Validation,我正在开发一个基于Spring引导的RESTAPI。我正在使用自定义ConstraintValidator注释验证输入实体。我的问题是,我无法在响应中返回ConstraintViolationException消息。我的异常处理程序没有捕获异常(可能是因为它们被包装在其他类型的异常中) 我能得到一些关于如何处理这种情况的建议吗 我在互联网上到处搜索,但找不到适合我的解决方案,我也浪费了一些时间 注释示例: @已记录 @保留(运行时) @目标({字段,参数}) @约束(validatedBy=Bi

我正在开发一个基于Spring引导的RESTAPI。我正在使用自定义ConstraintValidator注释验证输入实体。我的问题是,我无法在响应中返回ConstraintViolationException消息。我的异常处理程序没有捕获异常(可能是因为它们被包装在其他类型的异常中)

我能得到一些关于如何处理这种情况的建议吗

我在互联网上到处搜索,但找不到适合我的解决方案,我也浪费了一些时间

注释示例:

@已记录
@保留(运行时)
@目标({字段,参数})
@约束(validatedBy=BirthDateValidator.class)
public@interface ValidBirthDate{
字符串消息()默认值“出生日期无效。”;
类[]组()默认值{};

类在进一步调试之后,我发现所有违反约束的行为都被包装到一个
MethodArgumentNotValidException
(因为
@Valid
注释)-我必须在该异常中挖掘一些信息

我已经从
ResponseEntityExceptionHandler
中重写了
handleMethodArgumentNotValid()
方法,我就是这样让它工作的:

@覆盖
受保护的ResponseEntity handleMethodArgumentNotValid无效(MethodArgumentNotValidException ex、HttpHeaders标头、HttpStatus状态、WebRequest请求){
List errorMessages=new ArrayList();
BindingResult BindingResult=ex.getBindingResult();
列表错误=bindingResult.getAllErrors();
for(ObjectError错误:错误){
字符串消息=错误。getDefaultMessage();
errorMessages.add(消息);
}
返回新的ResponseEntity(新错误(errorMessages)、新HttpHeaders()、错误请求);
}

可能这对某人有帮助。

当目标参数无法通过验证时,Spring Boot会抛出一个
MethodArgumentNotValidException
异常。我已从该异常的
bindingResult
中提取错误消息,如下所示:

@RestControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

@Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
        //to extract the default error message from a diagnostic
        // information about the errors held in MethodArgumentNotValidException
        Exception exception = new Exception(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage());
        return this.createResponseEntity(HttpStatus.BAD_REQUEST, exception, request);
    }

private ResponseEntity<Object> createResponseEntity(
            HttpStatus httpStatus, Exception ex, WebRequest request) {
        ErrorResponse errorResponse = ErrorResponse.builder()
                .timestamp(LocalDateTime.now())
                .status(httpStatus.value())
                .error(httpStatus.getReasonPhrase())
                .message(ex.getMessage())
                .path(request.getDescription(true))
                .build();
        return handleExceptionInternal(ex, errorResponse,
                new HttpHeaders(), httpStatus, request);
    }

}
{
  "timestamp": "2021-01-20T10:30:15.011468",
  "status": 400,
  "error": "Bad Request",
  "message": "Due date should not be greater than or equal to Repeat Until Date.",
  "path": "uri=/api/tasks;client=172.18.0.5;user=109634489423695603526"
}
响应将为400,主体为JSON格式,如下所示:

@RestControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

@Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
        //to extract the default error message from a diagnostic
        // information about the errors held in MethodArgumentNotValidException
        Exception exception = new Exception(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage());
        return this.createResponseEntity(HttpStatus.BAD_REQUEST, exception, request);
    }

private ResponseEntity<Object> createResponseEntity(
            HttpStatus httpStatus, Exception ex, WebRequest request) {
        ErrorResponse errorResponse = ErrorResponse.builder()
                .timestamp(LocalDateTime.now())
                .status(httpStatus.value())
                .error(httpStatus.getReasonPhrase())
                .message(ex.getMessage())
                .path(request.getDescription(true))
                .build();
        return handleExceptionInternal(ex, errorResponse,
                new HttpHeaders(), httpStatus, request);
    }

}
{
  "timestamp": "2021-01-20T10:30:15.011468",
  "status": 400,
  "error": "Bad Request",
  "message": "Due date should not be greater than or equal to Repeat Until Date.",
  "path": "uri=/api/tasks;client=172.18.0.5;user=109634489423695603526"
}

我希望这能有所帮助。如果您需要关于类级约束的详细解释,请查看。

我还有一个通用异常处理程序(用于
异常
),但这也不能捕获它。我假设异常是由Spring内部处理并包装到其他内容中的,但我不知道这是什么。当对象验证失败时不应该抛出
ConstraintViolationException
isValid()
返回false)吗?您是否检查了
birthDate
是否为空?是(见上文)。在我的日志中或调试时没有发现异常。在另一个线程上,有人提醒我们RestController类还需要“@Validated”命令注释。这真的很有用,我正在努力提取精确的约束冲突,MethodArgumentNotValidException没有为我提供所需的结果,因为它是泛型的。在我提供了这样的代码之后,我能够深入了解约束错误。非常感谢!