处理由DefaultErrorAttributes覆盖的MethodArgumentNotValidException

时间:2018-04-07 16:09:53

标签: spring validation spring-mvc spring-boot spring-web

我的目标是为验证错误设置自定义响应正文。这是一个非常常见的案例,我已经阅读了很多帖子/博客/文章,我甚至在过去自己实现了这一点。出于某种原因,我无法弄清楚这一点。

我有@RestControllerAdvice

@Slf4j
@RequiredArgsConstructor
@RestControllerAdvice
public class ErrorHandler extends ResponseEntityExceptionHandler {

  private final MessageSource messageSource;

  @Override
  protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
      HttpHeaders headers, HttpStatus status, WebRequest request) {
    ValidationErrorDTO validationError = ValidationErrorDTO.builder()
        .fieldErrors(ex.getBindingResult().getFieldErrors().stream()
            .map(fieldError -> FieldErrorDTO.builder()
                .field(fieldError.getField())
                .message(messageSource.getMessage(fieldError, LocaleContextHolder.getLocale()))
                .build())
            .collect(Collectors.toList()))
        .build();
    LOGGER.debug("W3MnsZ validation error: {}", validationError);
    return new ResponseEntity<Object>(validationError, HttpStatus.BAD_REQUEST);
  }
}

====

@ToString
@Builder
public class ValidationErrorDTO {

  private final List<FieldErrorDTO> fieldErrors;
}

====

@ToString
@Builder
@Getter
@JsonInclude(Include.NON_NULL)
public class FieldErrorDTO {

  private final String field;
  private final String message;
}

我的ErrorHandler.handleMethodArgumentNotValid()被点击,但返回给客户的实际响应主体不是来自我的ValidationErrorDTO

{
  "timestamp": 1523115887261,
  "status": 400,
  "error": "Bad Request",
  "exception": "org.springframework.web.bind.MethodArgumentNotValidException",
  "errors": [
    {
      "codes": [
        "NotEmpty.myDTO.field.another.lastly",
        "NotEmpty.field.another.lastly",
        "NotEmpty.lastly",
        "NotEmpty.java.lang.String",
        "NotEmpty"
      ],
      "arguments": [
        {
          "codes": [
            "myDTO.field.another.lastly",
            "field.another.lastly"
          ],
          "arguments": null,
          "defaultMessage": "field.another.lastly",
          "code": "field.another.lastly"
        }
      ],
      "defaultMessage": "may not be empty",
      "objectName": "myDTO",
      "field": "field.another.lastly",
      "rejectedValue": null,
      "bindingFailure": false,
      "code": "NotEmpty"
    }
  ],
  "message": "Validation failed for object='myDTO'. Error count: 1",
  "path": "/myPath"
}

我已经发现org.springframework.boot.autoconfigure.web.DefaultErrorAttributes正在发生的事情正在受到重创,并以某种方式覆盖了我的自定义回复正文。

如何才能将自定义响应正文返回给客户端?

1 个答案:

答案 0 :(得分:0)

刚想通了。

ValidationErrorDTO.fieldErrors没有吸气剂。

@ToString
@Builder
@Getter
public class ValidationErrorDTO {

  @Singular
  private final List<FieldErrorDTO> fieldErrors;
}

现在它有效,我们得到回复:

{
  "fieldErrors": [
    {
      "field": "field.another.lastly",
      "message": "may not be empty"
    }
  ]
}