Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin和Spring引导请求主体验证_Spring_Validation_Spring Boot_Kotlin_Httprequest - Fatal编程技术网

Kotlin和Spring引导请求主体验证

Kotlin和Spring引导请求主体验证,spring,validation,spring-boot,kotlin,httprequest,Spring,Validation,Spring Boot,Kotlin,Httprequest,我刚刚开始使用kotlin和Spring Boot一起开发一个简单的web应用程序 让我们看一个简单的数据类对象 @Entity data class User (name: String) { @Id @GeneratedValue(strategy = GenerationType.AUTO) var id: Long = -1 } 和一个控制器 @RequestMapping(method = arrayOf(RequestMethod.POST)) fun

我刚刚开始使用kotlin和Spring Boot一起开发一个简单的web应用程序

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

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

@RequestMapping(method = arrayOf(RequestMethod.POST))
fun createUser (@RequestBody user: User): User {
    return userService.createUser(user)
}
嗯,使用任何请求体发出请求都会抛出http 400错误
未找到合适的构造函数,无法从对象值反序列化(缺少默认构造函数或创建者,或者可能需要添加/启用类型信息?);嵌套异常是com.fasterxml.jackson.databind.JsonMappingException

为了消除此错误,我发现我们需要为构造函数参数提供一些默认值,以便:

name: String = ""
或者可能:

name: String? = null
现在,响应体上的输入完全没有验证,这意味着,如果响应体中的JSON不遵守用户类的语法,将使用默认值并存储在数据库中

如果请求体JSON输入不符合用户类参数而不需要手动执行,是否有任何方法验证该输入以抛出错误的请求

在本例中,只有一个参数,但是手动处理较大的类似乎不是一个好方法


提前感谢

是的,有一些方法可以“自动”验证请求主体JSON


是其中之一,有几种实现。包括它,所以这可能是您的第一选择,因为Spring Boot将它包装得非常好。

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


API外观配置
验证机制
@服务
类ValidationService(validator:validator){
private val log=LoggerFactory.getLogger(ValidationService::class.java)
@抛出(BodyValidationException::类)
乐趣验证(o:T){
val冲突=验证程序。验证(o)
if(inflictions.isEmpty())返回
抛出BodyValidationException.of(inflictions.stream())
.map{v:ConstraintViolation->“${v.propertyPath}${v.message}”
.collect(收集器.toSet()).toMutableSet())
}
有趣的句柄(e:BodyValidationException):Mono=
handleInternal(错误响应(例如错误))
私人娱乐handleInternal(响应:ErrorResponse):Mono=
Mono.just(回应)
.doOnNext{res->log.warn(res.errors.joinToString(“,”)}
.flatMap{res->
badRequest().contentType(应用程序_JSON)
.bodyValue(res)
}
数据类错误响应(val错误:设置)
类BodyValidationException私有构造函数(变量错误:Set):IllegalArgumentException(){
伴星{
(错误:集合)的乐趣:BodyValidationException{
返回BodyValidationException(错误)
}
}
}
}

是的,您可以在User类的构造函数中或在userService调用的validations方法中执行此操作。您应该查看和(快速介绍)。它们使Spring+Kotlin数据类更容易接受。至于如何验证,如果您不介意繁重的模式文档,可以使用JsonSchema。这里有一个基本的例子,你注册了jackson kotlin模块()吗?一旦您这样做了,您就可以使用普通的javax.validation注释(只需记住注释使用站点目标)她的回答很有魅力。这与Paul Hicks提到的无参数构造函数有关,所以,感谢你们两位抽出时间来帮助我。如果需要更多的验证,JSON模式也可以工作needed@MiguelAnciães看看这个
@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)
            }
        }

    }
}