我试图在一个由@Validated注解的@RestController中验证一个由@Valid注解的简单请求体。验证在请求中的基元变量上可以正常工作(在下面的例子中,在年龄上),但在pojo请求体上却不能工作。@Valid注解对请求主体Person类(即控制器接受空白的名字和18岁以下的年龄)没有影响。
Person类。
import javax.validation.constraints.Min
import javax.validation.constraints.NotBlank
class Person (
@NotBlank
val name : String,
@Min(18)
val age : Int
)
控制器类:
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import javax.validation.Valid
@RestController
@Validated
class HomeController {
@GetMapping("/{age}")
fun verifyAge(@PathVariable("age") @Min(18) age:Int): String {
return "Eligible age."
}
@PostMapping
fun personValidation(@Valid @RequestBody person : Person) : String {
return "No validation error"
}
}
@NotBlank, @Min 和 @Valid 注解来自于下面的依赖关系。
implementation("org.springframework.boot:spring-boot-starter-validation:2.3.0.RELEASE")
如何让@Valid在@Validated控制器的Person请求体上工作?
不要将Person标记为Spring @Component。
实现字段验证的正确方法是在你的属性中添加@field。示例代码。
class SomeRequest(
@field:NotBlank val name: String
)
这是因为Spring Boot需要在字段上应用这种注解。Kotlin默认将其应用于构造函数参数。
你可以试试这个选项。
请将 @PostMapping 映射为一个 URL,比如 @PostMapping("validateBody"),然后用它的 URL 进行尝试。如同在 https:/reflectoring.iobean-validation-with-spring-boot。
经过4天的挖掘和多次命中和试验,在现有正确的最小配置的同时,发现了一个简单的变化。这个简单的改变就是在Person类上加上一个@Component注解,这样它的所有注解都可以按照@Component的Spring文档中提到的那样进行处理。
表示一个被注解的类是一个 "组件"。当使用基于注解的配置和classpath扫描时,这样的类被认为是自动检测的候选类。
新的person类将如下图所示(也将参数化的Person构造函数改为非参数化的,以便像Spring bean一样处理注解)。
import org.springframework.stereotype.Component
import javax.validation.constraints.Min
import javax.validation.constraints.NotBlank
@Component
class Person {
@NotBlank
private lateinit var name : String
@Min(18)
private var age : Int = 0
}
现在有了完整的最小化配置,结合问题和这个答案,现在@Valid annotations按照预期在请求体上调用POJO类,并按照Person类中指定的约束抛出ConstraintViolationException。