@valid注解未按预期工作

4
我将翻译以下内容:

我正在调用一个API,请求负载中包含对象数组,我已经添加了@valid注解以及@RequestBody来检查我的负载中是否发送了任何空属性。我期望如果我发送了任何空数据,它应该抛出一个错误。但是我的代码没有抛出错误。

以下是我的实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@DynamicUpdate
@Entity
@Table(name = "student")
public class Student {

   @Id
   @Column(name = "student_id")
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer studentId;

   @NotNull
   @Column(name = "name")
   private String name;

   @NotNull
   @Column(name = "gender")
   private String gender;

}

这是我的控制器类

@RestController
@CrossOrigin
public class StudentController {

   @PostMapping("/class/{classId}/student")
   public Student addStudent(@PathVariable Integer classId,@Valid @RequestBody List<Student>  
           student) {

     // My logic Comes Here
     return Student;
    }
  }

验证的依赖关系

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

我的请求负载

[{
   "name":"kiran",
   "gender":"male"
 },
 {
    "name":"divya"
 } 
]

当我发送上述有效载荷时,我希望会抛出一个错误,因为我没有发送 gender (性别),而它是非空的。但是 Spring 没有抛出任何错误。
我是否漏掉了某些 @valid 才能正常工作?

将@Validated注释添加到控制器类中。请参考https://www.baeldung.com/spring-validate-list-controller。 - wahyu eko hadi saputro
1
更详细的讨论可以在这个线程中找到:https://dev59.com/i14c5IYBdhLWcg3wOoO6 - sudipn
@bullzeye 谢谢,这对我很有效。你可以将其添加为解决方案。 - karthikmunna
7个回答

7
如果您使用的是Spring Boot 2.3.3.RELEASE版本,则需要在POM文件中添加以下依赖:
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

使用示例:

//update audTipo
@PutMapping("audTipo/{id}")
public ResponseEntity<AudTipo> update(@PathVariable(value="id") Integer audTipoId, 
        @Valid @RequestBody AudTipo audTipoDetils) throws ResourceNotFundException
{   
    
      AudTipo audTipo = audTipoRepository.findById(audTipoId).orElseThrow(()-> new
      ResourceNotFundException("NF " + audTipoId));
      audTipo.setXdesc(audTipoDetils.getXdesc());
      
      return ResponseEntity.ok(this.audTipoRepository.save(audTipo));    
}

这也适用于2.3.4.RELEASE版本。 - MatWdo

4

如果你遇到了例如无法看到返回给客户端的验证错误(默认信息)的问题,你可以采取以下措施:

最佳方案1: 只需添加devtools即可解决此问题。我这样做后,所有我的绑定结果都已返回给客户端。建议您首先测试一下:

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

解决方案2:

我发现这是由于使用了Spring Boot 2.3+版本造成的。因此,如果你正在使用Spring Boot 2.3或更高版本,请将以下依赖项添加到你的pom.xml文件中,因为它不再包含在“web”依赖项内。

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

现在必须将 java/resources/application.properties 中的 'include binding errors' 设置为“always”。同样适用于 'message',尽管我认为这是可选的。
server.error.include-message=always
server.error.include-binding-errors=always

解决方案3:(在我发现可能同样有用的解决方案2之前)

因此,我发现这是由于使用Spring Boot 2.3+造成的。但我找不到关于Spring Boot v2.3+中@Valid新更新用法的警告信息。

因此,我最终通过调整pom.xml文件中的版本号来切换回Spring Boot v2.2.10(2.2的最新版本),具体操作如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.10.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

通过回滚到旧版本,我成功解决了问题。尽管我希望有一天能够更新我的Spring Boot版本。(重新查看解决方案1和2)


1
由于我正在使用Spring 2.4版本,所以解决方案2适用于我。 - CodeNinja

3

2

你的@Valid注解是应用于列表而不是列表中实际存在的对象。

你例子中的注解验证的是列表而不是列表中每个对象。

尝试这样做:

public Student addStudent(@PathVariable Integer classId,@RequestBody List<@Valid Student> students)

你也可以指定其他参数,例如你可能需要验证列表中的每个对象,并确保列表不为空,或者具有最小大小等。这些验证必须在列表上执行。


不,即使将valid添加到对象中,它仍然无法正常工作。 - karthikmunna
2
在你的控制器上添加@Validated注解。它应该可以工作。 - sudipn

2

1
我知道你正在使用Maven构建,但我曾经遇到过相似的问题,即在Gradle构建中集成标签无法正常工作。
我通过获取正确版本的依赖项来解决这个问题。
implementation 'org.springframework.boot:spring-boot-starter-validation:2.4.0'

替代

implementation 'org.springframework.boot:spring-boot-starter-validation'

如果有人知道这是否正确,但现在它可以工作。

1
那可能不是原因。如果您正在使用io.spring.dependency-management,则只需要指定版本一次。也许运行gradle clean命令已经有所帮助了... - Tobias

0

当Spring Boot发现一个带有@Valid注释的参数时,它会自动引导默认的JSR 380实现——Hibernate Validator,并验证该参数。

只有在请求本身为NULL时,才会违反JSR 380实现。如上所述,它不能用于检查请求体中的null值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接