Spring 引导请求正文验证在输入无效数据类型时添加自定义消息

Spring Boot request body validation add customize messages when input an invalid data type

我正在使用 Spring Boot 创建一个 POST 请求,我需要根据用户输入验证请求正文。但是,当用户输入无效数据类型时,响应什么也不显示,只显示 400 bad request 状态。我可以添加一条消息来向用户显示哪个字段是无效数据类型吗?

例如: 这是我的控制器:

@RestController
@RequestMapping("/api/foo")
public class FooController {

  @PostMapping("/save")
  public void postFoo(@Valid @RequestBody Foo foo) {
    // do somethings
  }
}

这是我的 Foo class:

public class Foo {
  @NotBlank
  private String name;
  private Integer age;

  // getter/setter
}

所以现在我post一个请求如下:

{
  "name": "Foo Name",
  "age": "A String"
}

服务器将以 400 Bad request 状态响应,但没有任何消息。我怎样才能把我的消息,如 Age must be an integer.

直到现在我只有一个解决方案,将 Age 更改为 String 并添加 @Pattern 验证注释。

public class Foo {
  @NotBlank
  private String name;
  @Pattern(regexp = "[0-9]*", message = "Age must be an intege")
  private String age;

  // getter/setter
}

在您的 post 方法签名中,您可以使用响应实体 class 来显示一些要返回给用户的异常消息,以及一些状态代码。

public class FooController{

public ResponseEntity<?> showError()

{

return new ResponseEntity<>("Exception arised", HttpStatus.BAD_REQUEST);

}

}

您需要实现错误处理机制。

在您的错误处理程序中,您需要捕获所有异常和 return 错误响应。 这是一个基于 Controller 级别 ExceptionHandling

的示例
public class FooController{

   //...
   @ResponseStatus(value=HttpStatus.BAD_REQUEST)
   @ExceptionHandler({ CustomException1.class, CustomException2.class })
      public ErrorResponse handleException() {
      //
   }
}

在 ErrorResponse 模型中,您可以根据异常设置错误代码和消息,并通过 ResponseStatus 分配 http 错误代码

然而,他的方法有一个主要缺点:@ExceptionHandler 注释方法仅对特定控制器有效,而不是对整个应用程序全局有效。

要全局处理异常,您可以使用 ControllerAdvice。 Here 是一篇关于整体错误处理机制的好文章

谢谢大家。我找到了一种方法来添加消息并响应用户可以通过使用 ControllerAdvice 并覆盖 handleHttpMessageNotReadable 方法来意识到错误,如下例所示:

@ControllerAdvice
public class ErrorHandlerConfig extends ResponseEntityExceptionHandler {
 @Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers,
                                                              HttpStatus status, WebRequest request) {
    if (ex.getCause() instanceof InvalidFormatException) {
        InvalidFormatException iex = (InvalidFormatException) ex.getCause();
        List<Map<String, String>> errors = new ArrayList<>();
        iex.getPath().forEach(reference -> {
            Map<String, String> error = new HashMap<>();
            error.put(reference.getFieldName(), iex.getOriginalMessage());
            errors.add(error);
        });

        return handleExceptionInternal(ex, errors, new HttpHeaders(), apiError.getStatus(), request);
    }
    return super.handleHttpMessageNotReadable(ex, headers, status, request);
}
}

响应将是:

[
    {
        "testId": "Cannot deserialize value of type `java.lang.Long` from String \"accm\": not a valid Long value"
    }
]