[英]Kotlin Spring Boot bean validation not working
I have quite a few projects that is slowly being migrated from Java to Kotlin, but I'm facing a problem when changing from Java POJO to Kotlin data classes. I have quite a few projects that is slowly being migrated from Java to Kotlin, but I'm facing a problem when changing from Java POJO to Kotlin data classes. Bean validation stops working in REST controllers.
Bean 验证在 REST 控制器中停止工作。 I have created a very simple project directly from https://start.spring.io to demonstrate the failure.
我直接从https://start.spring.io创建了一个非常简单的项目来演示失败。
@SpringBootApplication
class RestValidationApplication
fun main(args: Array<String>) {
runApplication<RestValidationApplication>(*args)
}
@RestController
class Controller {
@PostMapping
fun test(@Valid @RequestBody request: Test) {
println(request)
}
}
data class Test(@field:NotNull val id: String)
and gradle:和 gradle:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.6.1"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.6.0"
kotlin("plugin.spring") version "1.6.0"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
Sending a request does not trigger the bean validation, but it throws a HttpMessageNotReadableException
because id
is NULL.发送请求不会触发 bean 验证,但会抛出
HttpMessageNotReadableException
,因为id
是 NULL。
curl -X POST http://localhost:8080 -H "Content-Type: application/json" -d "{}"
I have tried both @Valid
and @Validated
and using @get:NotNull
on the attributes, but nothing works.我已经尝试了
@Valid
和@Validated
并在属性上使用了@get:NotNull
,但没有任何效果。 I see many others have the same problem and using a Java class from a Kotlin REST controller works. I see many others have the same problem and using a Java class from a Kotlin REST controller works. Also changing to a non data class makes validation works.
更改为非数据 class 也可以进行验证。 Anyone know if it's possible to get bean validation working with Kotlin data classes?
任何人都知道是否可以使用 Kotlin 数据类进行 bean 验证?
Do not use data class for validation不要使用数据 class 进行验证
when you use data class you need to add @field:{} before annotation or you can use class without data class.当您使用数据 class 时,您需要在注释之前添加 @field:{} ,或者您可以在没有数据 class 的情况下使用 class。
data class:数据 class:
class AuthorInput(
@field:NotBlank @field:Size(max = 20, min = 3) val first_name: String? = null,
@field:NotBlank @field:Size(max = 20, min = 3) val last_name: String? = null,
@field:NotEmpty val role: List< String?>? = null
){
}
only class:仅 class:
class AuthorInput {
@NotBlank
@Size(max = 20, min = 3)
val first_name: String? = null
@NotBlank
@Size(max = 20, min = 3)
val last_name: String? = null
@NotEmpty
val role: List<@NotBlank String?>? = null
}
I think you are just missing @Validated annotation on top of your controller class.我认为您只是缺少 controller class 顶部的 @Validated 注释。
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
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.RequestMapping
import org.springframework.web.bind.annotation.RestController
import javax.validation.Valid
import javax.validation.constraints.NotEmpty
@SpringBootApplication
class BootValidationApplication
fun main(args: Array<String>) {
runApplication<BootValidationApplication>(*args)
}
@RestController
@RequestMapping("/api/v1")
@Validated
class CustomerController {
@PostMapping("/customer")
fun createCustomer(@Valid @RequestBody customer: Customer) {
println(customer)
}
}
data class Customer(@field:NotEmpty val name: String)
The issue has been fixed in Kotlin version 1.6.10.该问题已在 Kotlin 版本 1.6.10 中得到修复。 https://github.com/JetBrains/kotlin/releases/tag/v1.6.10 .
https://github.com/JetBrains/kotlin/releases/tag/v1.6.10 。 After upgrading the exception is now
org.springframework.web.bind.MethodArgumentNotValidException
.升级后的异常现在是
org.springframework.web.bind.MethodArgumentNotValidException
。
Make the field nullable even its not, and then add @field:NotNull使字段可以为空,即使它不是,然后添加 @field:NotNull
data class Test(@field:NotNull val id: String?)数据 class 测试(@field:NotNull val id: String?)
This will stop kotlin validation to happen before javax这将停止 kotlin 验证在 javax 之前发生
You have to add @get:Valid before.您必须先添加 @get:Valid 。 For example:
例如:
data class Location(
@get:Valid @get:DecimalMin("-90") @get:DecimalMax("90") val lat: Double,
@get:Valid @get:DecimalMin("-180") @get:DecimalMax("180") val lng: Double
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.