【问题标题】:Validation response is missing errors details验证响应缺少错误详细信息
【发布时间】:2020-11-19 12:49:40
【问题描述】:

我有一个 Spring Boot Rest Controller,它接收一个带有验证字段的帖子正文。如果我发送违反验证的正文,我会收到错误响应。

但在该回复中,我缺少对错误的详细描述,即验证的哪一部分失败。在后端记录的异常中,这包括在内,但我希望对客户端可见:

HTTP 响应:

{
  "timestamp": "2020-11-19T12:15:34.957+00:00",
  "status": 400,
  "error": "Bad Request",
  "message": "Validation failed for object='postBody'. Error count: 1",
  // <-- here I am missing the errors field that contains the (list of) error messages.
  "path": "/comments"
}

控制器和 PostBody:

@RestController
@Validated
public class CommentsController {

    public void createComment(PostBody postBody) {
      //do stuff
    }
}

public class PostBody {
    private String text;

    @Size(max = 10) 
    public String getText() {
        return text;
    }
    // setter
}

后端日志中的异常包含错误:

2020-11-19 13:15:34 WARN  o.s.w.s.m.s.DefaultHandlerExceptionResolver - 
    Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in 
    public CommentsController.createComment(PostBody): 
    [Field error in object 'postBody' on field 'text': rejected value [my very long input]; 
    codes [Size.postBody.text,Size.text,Size.java.lang.String,Size]; arguments 
    [org.springframework.context.support.DefaultMessageSourceResolvable: codes [postBody.text,text]; 
    arguments []; default message [text],10,0]; default message [size must be between 0 and 10]] ]

我是否需要配置任何其他内容才能将错误详细信息放入响应中?我希望这是开箱即用的。

【问题讨论】:

    标签: java spring-boot validation


    【解决方案1】:

    我必须在我的application.yml 中添加server.error.include-binding-errors: always 才能在错误响应中启用"errors" 字段:

    所以我的application.yml 现在是:

    server:
      error:
        include-message: always
        include-binding-errors: always
    

    响应如下所示。这个比我想象的要详细,但是里面包含了需要的信息,不需要写代码,只需要配置:

    {
      "timestamp": "2020-11-19T12:15:34.957+00:00",
      "status": 400,
      "errors": [
        {
          "codes": [
            "Size.postBody.text",
            "Size.text",
            "Size.java.lang.String",
            "Size"
          ],
          "arguments": [
            {
              "codes": [
                "postBody.text",
                "text"
              ],
              "arguments": null,
              "defaultMessage": "text",
              "code": "text"
            },
            10,
            0
          ],
          "defaultMessage": "size must be between 0 and 10",
          "objectName": "postBody",
          "field": "text",
          "rejectedValue": "my very long input",
          "bindingFailure": false,
          "code": "Size"
        }
      "error": "Bad Request",
      "message": "Validation failed for object='postBody'. Error count: 1", messages.
      "path": "/comments"
    }
    

    application.yml 中我已经配置了字段server.error.include-message: always。否则错误响应中的"message": 值将只是一个空字符串。

    这里是关于它的 GitHub 讨论:https://github.com/spring-projects/spring-boot/issues/20505#issuecomment-621295137

    【讨论】:

      【解决方案2】:

      我建议你使用一种方法来检查你的实体验证,有一个例子

       private void checkIfReadyToSave(PostBody myPost) {
          Set<ConstraintViolation<Product>> violations =
              validator.validate(product, PostBodyCreation.class);
          if (!violations.isEmpty()) {
            Map<String, Object> body = new LinkedHashMap<>();
            Set<String> keys =
                violations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());
            body.put("errors", keys);
            throw new BeanValidationException(ErrorConstants.POST_BODY_MISSING_ERROR_MSG, body.toString());
          }
        }
      

      这就是你如何使用弹簧验证来验证你的模型

      public class PostBody {
      
      
      
      @NotBlank(groups = PostBodyCreation.class, message = "text.notSetted")
      @Field("text")
      private String text;
      

      这是如何制作验证界面:

      import javax.validation.groups.Default;
      
      public interface PostBodyCreation extends Default {
      }
      

      【讨论】:

      • 我正在使用 openAPI 生成的 requestBody 对象,所以我猜想在字段上添加自定义验证器会很复杂。
      • 您可以将其添加到您的模型中,该模型将映射开放的 API 请求对象
      猜你喜欢
      • 2018-09-30
      • 1970-01-01
      • 2012-05-13
      • 2023-01-04
      • 1970-01-01
      • 2023-04-07
      • 2012-09-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多