Kotlin Spring Boot Webflux 使用 @Valid 注解验证 @RequestBody

Posted

技术标签:

【中文标题】Kotlin Spring Boot Webflux 使用 @Valid 注解验证 @RequestBody【英文标题】:Kotlin Spring Boot Webflux validate @RequestBody with @Valid annotation 【发布时间】:2022-01-01 03:15:49 【问题描述】:

我在带有 Webflux 的 Spring Boot 中有一个简单的 REST API。 我想在我的 POST 请求中对请求正文使用基于注释的简单验证。

RecipeModel.kt

package com.example.reactive.models

import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table
import org.springframework.stereotype.Component
import javax.validation.constraints.Max
import javax.validation.constraints.NotBlank

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

RecipeRepo.kt

package com.example.reactive.repositories

import com.example.reactive.models.Recipe
import org.springframework.data.repository.reactive.ReactiveCrudRepository
import org.springframework.stereotype.Repository

@Repository
interface RecipeRepo : ReactiveCrudRepository<Recipe, Long>

RecipeController.kt

package com.example.reactive.controllers

import com.example.reactive.models.Recipe
import com.example.reactive.models.RecipeMapper
import com.example.reactive.repositories.RecipeRepo
import com.example.reactive.services.RecipeService
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*
import reactor.core.publisher.Flux
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: @Valid Recipe): Mono<Recipe> =
        recipeService.createRecipe(payload)



RecipeService.kt

package com.example.reactive.services

import com.example.reactive.models.Recipe
import com.example.reactive.models.RecipeMapper
import com.example.reactive.repositories.RecipeRepo
import org.springframework.stereotype.Service
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono

@Service
class RecipeService(val recipeRepo: RecipeRepo, val recipeMapper: RecipeMapper) 


    fun createRecipe(recipe: Recipe): Mono<Recipe> = recipeRepo.save(recipe)


期望:当我提供带有空字符串作为标题和/或超过 10 个字符的描述的 POST 请求时,我不应该得到 201 CREATED 作为响应。

Checking with Postman

如您所见,我收到 201 CREATED 作为响应。

有人看到我哪里出错了吗???

【问题讨论】:

你可以尝试将@Validated添加到控制器中 【参考方案1】:

您需要在控制器中进行一些更改(@Valid 位置):

@RestController
@RequestMapping("/recipes")
class RecipeController(val recipeService : RecipeService) 
 
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    fun createRecipe(@RequestBody @Valid payload: Recipe): Mono<Recipe> =
        recipeService.createRecipe(payload)

还有在模型本身中(你需要使用@field:):

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

【讨论】:

它似乎正在使用(at)field .. 感谢您的解决方案。这是(at)字段的新功能吗?在我试图解决我的问题时,在数小时的研究中从未见过任何与 (at)field 相关的示例。所有示例都只是 (at)NotBlank / (at)Max 等 问题是您可能正在阅读 Java 的示例,而不是 Kotlin。你可以在这里阅读更多内容 --> kotlinlang.org/docs/… 我认为这确实是问题所在。据我所知,大多数示例都是用 Java 编写的。再次感谢! 不客气! ;)

以上是关于Kotlin Spring Boot Webflux 使用 @Valid 注解验证 @RequestBody的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 与 Kotlin 上传文件

Spring Boot (kotlin) 循环依赖

Spring Boot没有使用Jackson Kotlin插件

干货丨Kotlin在Spring Boot中的应用

Spring Boot 2 和 Kotlin(使用 Maven)

Kotlin和Spring Boot请求身体验证