Spring Boot - 验证@RequestBody
Posted
技术标签:
【中文标题】Spring Boot - 验证@RequestBody【英文标题】:Springboot - validate @RequestBody 【发布时间】:2021-02-07 13:17:27 【问题描述】:问题:是否可以验证请求正文的 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");
解决此问题的最有效方法是什么?某种注释?或者也许是 Spring 启动配置?
谢谢
【问题讨论】:
是的,您使用的是原语,这就是您得到 0 的原因。您可以使用 Integer,然后当您不发送节点时您将获得 null。您可以使用 @NotNull 来验证该字段。并在@RequestBody
上使用@Valid
一篇关于验证的好文章here
请问是否有可能在保持 int 类型而不是 Integer 的情况下实现相同的效果?
是的,您可以使用@Min(1)
并在@RequestBody
上使用@Valid
。阅读here了解详情
reflectoring.io/bean-validation-with-spring-boot
【参考方案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
【讨论】:
请问是否有可能实现相同的保持类型 int,而不是 Integer? (为帖子点赞) 你可以这样配置Jackson,当它尝试使用DeserializationFeature
将null
(缺少的字段)反序列化为int
时会抛出DeserializationException:FAIL_ON_NULL_FOR_PRIMITIVES
fasterxml.github.io/jackson-databind/javadoc/2.4/index.html?com/…
@ŁukaszMonkiewicz 链接已损坏
@RBz 试试这个:lmonkiewicz.medium.com/…
您还需要将这些添加为依赖项才能使用 @Valid
、 @NotNull
等。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
【参考方案2】:
已经提供的answer 涵盖了答案。
不过,我想详细说明您问的一件事。
如何在这方面失败 "importantWithTypo": 42,
它的两个方面。
-
如果必填字段不存在,您希望返回 4XX(这可以通过已经给出的答案来实现) -- @NonNull/@NonEmpty 与 @Validate 注释结合使用
您想在存在未知字段
importantWithTypo
时出错。这可以通过杰克逊的 fail_on_unknown_properties 属性来实现。 (可能默认为fail_on_unknown_properties = enabled,我没有检查所以不确定)。
不要做这第二件事。这将使您的 2 个服务紧密耦合。通过执行此 fail_on_unknown_properties = enabled,您将失去以不间断方式增强消费者/呼叫者服务的潜在机会。您必须协调两个应用程序的发布。
【讨论】:
以上是关于Spring Boot - 验证@RequestBody的主要内容,如果未能解决你的问题,请参考以下文章
在 Tomcat 上使用 Spring Boot 进行身份验证
通过 spring-boot 进行 Spring WS UsernameToken 身份验证 + 会话管理