带有缺失字段名称的错误请求响应 - Spring 启动

Bad Request response with name of missing field - Spring Boot

我有一个 API 端点,它获取名称和描述参数(两者都是必需的)

createSomething(@RequestParam(value = "name") String name,@RequestParam(value = "description") String description)

如果客户没有提供任何这些,他将收到 400 Bad Request

有没有办法告诉客户缺少哪个字段?为“错误请求”响应提供更多信息

更新:请注意参数必须是必需的,因为我希望 OpenAPI 将检测到这些参数是必需的。因此,像“可选”和检查函数体内这样的解决方案并不是我想要的

您可以对自定义消息使用验证:

@GetMapping("/name-for-month")
public String getNameOfMonthByNumber(@RequestParam @Min(1) @Max(value = 12, message = “month number has to be less than or equal to 12”) Integer month) {
// ...
}

有很多处理 Rest 错误的方法,在下面 link 中至少有 5 种解决方案可以解决您的问题:

  1. 异常处理程序
  2. HandlerExceptionResolver(ResponseStatusExceptionResolver 这是最适合您的情况,如果您使用 spring 5+,则为第 4 个)
  3. 控制器建议
  4. 响应状态异常
  5. 处理 Spring 安全中的拒绝访问

https://www.baeldung.com/exception-handling-for-rest-with-spring

由于这两个参数都是强制性的,如果您尝试不带参数发送请求,您将收到 400(错误请求)。

一种解决方法是制作请求参数non-mandatory(以便可以在没有参数的情况下发送请求)并在未提供参数的情况下提供默认值

createSomething(@RequestParam(value = "name", required=false, defaultValue = null) String name,@RequestParam(value = "description", required=false, defaultValue = null) String description)

在函数中,你可以像下面这样检查null -

if (name == null) // name parameter is not provided
if (description == null) // description paramter is not provided

并且,如果请求中未提供任何 one/more 参数,您还可以根据条件发送错误响应。

我看到了多个答案,但没有一个足够具体。

1)

Spring 默认情况下能够在错误消息中报告缺少的参数或请求中的其他违规行为。

然而,自 spring 引导版本 2.3 以来,特定的错误消息被隐藏,因此不会向用户泄露任何敏感信息。

您可以使用2.3版本之前的默认机制属性 server.error.include-message: always并允许spring再次为您编写错误信息。

2)

如果您负担不起,因为其他敏感信息可能会从其他异常中泄露出来,那么您必须为这种特定情况提供自己的异常处理程序

以下可以放在同一个控制器中,也可以放在另一个标有@ControllerAdvice

的class中
@ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseEntity handleMissingParams(MissingServletRequestParameterException ex) {
    return ResponseEntity.badRequest().body(String.format("Missing parameter with name:%s", ex.getParameterName()));
}

正如@Shubam 所说,您可以通过将 required 属性设置为 true 来使用 @RequestParam 注释的 defaultValue 属性,因为这两个参数都是必需的。 这是您如何操作的示例,

private final String DEFAULT_NAME = "Default Name";
private final String DEFAULT_DESC = "Default Desc";
@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<String> createSomething(@RequestParam(required = true, name = "name", defaultValue = "Default Name") String name,
                                   @RequestParam(required = true, name = "description", defaultValue = "Default Desc") String desc){
    if(DEFAULT_NAME.equals(name)){
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Field Name is missing");
    }
    if(DEFAULT_DESC.equals(desc)){
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Field Desc is missing");
    }
    return ResponseEntity.ok(String.format("Hello, %s!",name));
}