【问题标题】:@Valid Not working @PostMapping spring boot@Valid 不工作 @PostMapping 春季启动
【发布时间】:2021-07-15 21:07:05
【问题描述】:

我正在学习 Spring Boot,我正在为 @PostMapping 添加验证,但不知何故,即使值无效,它也总是会创建一个对象。

医院.java

public class Hospital {
    private Integer id;
    @Size(min = 2)
    private String name;
    @Size(min = 2)
    private String city;

    public Hospital(Integer id, String name, String city) {
        this.id = id;
        this.name = name;
        this.city = city;
    }

控制器

@Autowired
    HospitalData data;
...
@PostMapping("/hospital")
    public ResponseEntity<Hospital> addHospital(@Valid @RequestBody Hospital hospital){
        Hospital newHospital = data.addHospital(hospital);

        URI location = ServletUriComponentsBuilder
        .fromCurrentRequest()
        .path("/{id}")
        .buildAndExpand(newHospital.getId()).toUri();

        return ResponseEntity.created(location).build();
    }

pom.xml

<dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
        </dependency>

之前我在使用Spring 2.3.10 RELEASE时添加了下面的依赖,但是它不起作用,所以我添加了上面的依赖。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

【问题讨论】:

  • 使用 spring-boot-starter-validation,就像在这篇文章中描述的那样:baeldung.com/spring-boot-bean-validation 我认为这没有理由不起作用。
  • 给我们一些具体的例子,说明哪些无效值已经通过而没有失败
  • @Size(min = 2) 并不意味着它不能为空。在这种情况下,您还需要另一个注释 @NotNull
  • @Boug :我添加了@NotNull 和@Size(min=2),当我通过{ "name": "b", "city": "A" } 时,它仍然创建了201。

标签: java spring spring-boot validation


【解决方案1】:

我创建了一个测试应用程序来重现您的代码状态。如 cmets 中所述,您提供的代码绝对可以工作。您绝对不需要为该方法提供BindingResult。 Spring Boot 抛出一个MethodArgumentNotValidException,因此返回一个错误的请求 http 状态验证失败。

我创建了一个包含以下内容的项目:

pom.xml

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.5</version>
</parent>
<properties>
    <java.version>11</java.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

演示实体:

public class DemoEntity {
    @NotNull
    public String name;
    @Size(min = 3)
    public String greeting;
}

演示控制器:

@Controller
public class DemoController {
    @PostMapping("/post")
    public ResponseEntity<DemoEntity> put(@Valid @RequestBody DemoEntity demoEntity) {
        return ResponseEntity.ok(demoEntity);
    }
}

现在,我的请求就是这样:

Name Greeting Result
Peter Mr 400
Stephen Monsieur 200
Clara null 200
Jenny Madamme 200

如上表所示,当greetingnull 时,结果为正常状态。如果要保证字符串至少为min 个字符长并且 不为空,则需要显式声明。

例如,如果您想验证手机号码等可选字段。你知道,它应该是 n 个数字,并且只包含数字,但你不想让它成为强制性的。就像我在上面的问候中展示的那样。

【讨论】:

  • 谢谢,我有一些奇怪的经历,我删除了我在邮递员中传递的 json 正文,然后我再次输入了相同的 json 正文,现在我得到了正确的验证响应和正确的 HTTPStatus。
【解决方案2】:

您需要将 BindingResult 对象作为参数注入表单对象之后,然后手动检查是否有任何错误。

请参阅 https://spring.io/guides/gs/validating-form-input/ 创建 Web 控制器,了解如何在控制器中完成此操作的一个很好的示例。

【讨论】:

  • 不幸的是,这是错误的。正如我在回答中所展示的,OP 提供的代码有效。我假设请求包含空值。
  • 可能,但是接收表单帖子的帖子控制器仍然需要使用 BindingResult 对象,以便它可以智能地转发到正确的页面以显示错误并要求更正的输入。
  • 这取决于几个方面。如果 OP 只是为应该验证的数据提供 api,他不需要提供用户信息。是的,这会很好(他可以在异常处理程序中实现这一点,就像我链接的那样),但不是必需的。特别是如果他在多个请求中使用该实体。
猜你喜欢
  • 1970-01-01
  • 2015-11-21
  • 2018-01-13
  • 1970-01-01
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多