gpt4 book ai didi

spring - Kotlin 和 Spring Boot 请求正文验证

转载 作者:行者123 更新时间:2023-12-02 12:02:52 24 4
gpt4 key购买 nike

我刚刚开始使用 kotlin 和 Spring Boot 来开发一个简单的 Web 应用程序。

让我们来看一个简单的数据类对象

@Entity  
data class User (name: String) {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
var id: Long = -1
}

和一个 Controller
@RequestMapping(method = arrayOf(RequestMethod.POST))
fun createUser (@RequestBody user: User): User {
return userService.createUser(user)
}

好吧,使用任何请求正文发出请求只会引发 http 400 错误 no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException
为了消除这个错误,我发现我们需要为构造函数参数提供一些默认值,因此:
name: String = ""

或者可能:
name: String? = null

现在,响应正文中的输入绝对没有验证,这意味着,如果其中存在的 JSON 不遵守 User 类的语法,则将使用默认值并将其存储在数据库中。

是否有任何方法可以验证请求正文 JSON 输入以抛出错误请求(如果它不符合 User 类参数而无需手动执行)?

在这个例子中只有一个参数,但手动使用更大的类似乎不是一个好方法

提前致谢

最佳答案

我认为以下由两部分组成的解决方案可以用于 Spring Boot 2.x :

API 门面配置

@Configuration
class ValidationRouter(
val validationService: ValidationService
) {

@Bean
fun router() = router {
accept(APPLICATION_JSON).nest {
"/api".nest {
POST("/validation") { req ->
req.bodyToMono(ValidatingBody::class.java)
.doOnNext(validationService::validate)
.flatMap { ServerResponse.ok().build() }
.onErrorResume(BodyValidationException::class.java, validationService::handle)
}
}

}

}

data class ValidatingBody(
@get:NotBlank(message = "should not be blank")
var mandatoryText: String?,
@get:Size(min = 2, max = 10, message = "should contain more than 2 and less than 10 characters")
@get:NotBlank(message = "should not be blank")
var sizedText: String?,
@get:Min(value = 1, message = "should be no less than 1")
@get:Max(value = 10, message = "should be no greater than 10")
@get:NotNull(message = "should be specified")
var limitedNumber: Int?
)
}

验证机制
@Service
class ValidationService(val validator: Validator) {

private val log = LoggerFactory.getLogger(ValidationService::class.java)

@Throws(BodyValidationException::class)
fun <T> validate(o: T) {
val violations = validator.validate(o)
if (violations.isEmpty()) return

throw BodyValidationException.of(violations.stream()
.map { v: ConstraintViolation<T> -> "${v.propertyPath} ${v.message}" }
.collect(Collectors.toSet()).toMutableSet())
}

fun handle(e: BodyValidationException): Mono<ServerResponse> =
handleInternal(ErrorResponse(e.errors))

private fun handleInternal(response: ErrorResponse): Mono<ServerResponse> =
Mono.just(response)
.doOnNext { res -> log.warn(res.errors.joinToString(",")) }
.flatMap { res ->
badRequest().contentType(APPLICATION_JSON)
.bodyValue(res)
}

data class ErrorResponse(val errors: Set<String>)

class BodyValidationException private constructor(var errors: Set<String>) : IllegalArgumentException() {
companion object {
fun of(errors: Set<String>): BodyValidationException {
return BodyValidationException(errors)
}
}

}
}

关于spring - Kotlin 和 Spring Boot 请求正文验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49040565/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com