You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Spring Boot Webflux中@Valid注解校验@RequestBody不生效问题

问题原因及解决方案

你遇到的校验不生效是4个常见的WebFlux+Kotlin参数校验组合问题,按顺序修改即可:

1. 校验注解使用错误

@Max是JSR-380规范中用于数值类型的校验注解,不能用来校验字符串长度,你需要替换为@Size注解来限制字符串长度。

2. Kotlin数据类注解作用域错误

Kotlin中直接写在数据类主构造参数上的校验注解,默认是标注在构造参数而非类字段上,校验框架无法读取,需要给注解加上field:前缀指定作用于字段。

3. WebFlux请求体验写规则错误

Spring WebFlux是响应式框架,请求体需要用Mono/Flux包裹,同时@Valid注解需要标注在泛型内部的实体类上,才能触发校验逻辑。

4. 缺失校验依赖

Spring Boot 2.3及以上版本中,spring-boot-starter-webflux不再默认集成校验组件,需要手动引入校验依赖:

<!-- Maven 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
// Gradle 依赖
implementation 'org.springframework.boot:spring-boot-starter-validation'

修改后的代码示例

修改后Recipe实体类

package com.example.reactive.models

import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table
import javax.validation.constraints.NotBlank
import javax.validation.constraints.Size

@Table("recipes")
data class Recipe (
    @Id
    val id: Long?,
    @field:NotBlank(message = "Title is required") 
    val title: String,
    @field:Size(max = 10, message = "Description is too long") 
    val description: String?,
)

修改后Controller代码

package com.example.reactive.controllers

import com.example.reactive.models.Recipe
import com.example.reactive.services.RecipeService
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*
import reactor.core.publisher.Mono
import javax.validation.Valid

@RestController
@RequestMapping("/recipes")
class RecipeController(val recipeService : RecipeService) {

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    fun createRecipe(@RequestBody payload: Mono<@Valid Recipe>): Mono<Recipe> =
        payload.flatMap(recipeService::createRecipe)
}

可选优化:统一异常返回

如果需要返回结构化的校验错误信息,可以新增全局异常处理器捕获WebFlux校验抛出的WebExchangeBindException:

@ControllerAdvice
class GlobalExceptionHandler {
    @ExceptionHandler(WebExchangeBindException::class)
    fun handleValidException(e: WebExchangeBindException): ResponseEntity<Map<String, String?>> {
        val errors = e.bindingResult.fieldErrors.associate { it.field to it.defaultMessage }
        return ResponseEntity.badRequest().body(errors)
    }
}

内容的提问来源于stack exchange,提问作者paswes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 01:15:01