春靴 - 验证@RequestBody

2022-09-03 00:51:47

问:是否可以验证请求正文的 JSON 有效负载,而无需专门编写 if 语句?也许通过注释或配置?

我有一个非常简单的POJO:

public class Foo {

    private int important;
    private String something;

//constructors, getter, seters, toString
}

还有一个非常简单的控制器类:

@SpringBootApplication
@RestController
public class QuestionController {

    public static void main(String[] args) {
        SpringApplication.run(QuestionController.class, args);
    }

    @GetMapping(value = "/question")
    Mono<String> question(@RequestBody Foo foo) {
        System.out.println("The object foo, with value for important = " + foo.getImportant() + " and something = " + foo.getSomething());
        return Mono.just("question");
    }

}

如果我使用有效负载进行查询,例如:

{
    "important": 42,
    "something": "value"
}

一切都很好,非常满意。

但是,如果有拼写错误:(请注意“重要”上的拼写错误)

{
    "importantWithTypo": 42,
    "something": "value"
}

或者缺少所需的“重要”(请注意,JSON甚至不完整)

{
    "something": "value"
}

请求和计算仍然有效!而“重要”的值为0!

我不希望Spring默认为0,并认为一切都很好。

我也不想将我的类型从基元更改为盒装对象。

没有我写这样的东西:

 @GetMapping(value = "/question")
    Mono<String> question(@RequestBody Foo foo) {
        if (0 == foo.getImportant()) {
            throw new IllegalArgumentException();
        }
        System.out.println("The object foo, with value for important = " + foo.getImportant() + " and something = " + foo.getSomething());
        return Mono.just("question");
    }

解决此问题的最有效方法是什么?某种注释?或者也许是弹簧启动配置?

谢谢


答案 1

在字段上添加@NotNull注释(可能需要将类型更改为 Integer),并在控制器的方法参数上添加@Valid注释。

Mono<String> question(@Valid @RequestBody Foo foo) {
    ...
}
public class Foo {

    @NotNull
    private Integer important;
    private String something;

//constructors, getter, seters, toString
}

您可以在此处找到更多信息:https://lmonkiewicz.medium.com/the-power-of-spring-rest-api-validation-77be83edef


答案 2

已经提供的答案涵盖了答案。

但是,我想详细阐述你问的一件事。

如何在这个“重要与Typo”上失败:42,

2个方面。

  1. 如果必填字段不存在,您希望返回4XX(这可以通过已经给出的答案来实现) - @NonNull / @NonEmpty与@Validate注释结合使用
  2. 您希望在存在未知字段 时出错。这可以通过杰克逊fail_on_unknown_properties属性来实现。(可能是默认fail_on_unknown_properties=启用,我没有检查所以不确定)。importantWithTypo

不要做这第二件事。这将使您的2个服务紧密耦合。通过执行此操作fail_on_unknown_properties = 启用,您将失去以不间断的方式增强使用者/呼叫者服务的潜在机会。您将必须协调两个应用程序版本。