简体   繁体   English

Spring webflux bean 验证不起作用

[英]Spring webflux bean validation not working

I am trying to use bean validation in Webflux.我正在尝试在 Webflux 中使用 bean 验证。 This is what I have so far:这是我到目前为止:

@PostMapping("contact")
fun create(@RequestBody @Valid contact: Mono<Contact>) : Mono<Contact> {
    return contact.flatMap { contactRepository.save(it) }
            .doOnError{ Error("test") }
}

The The validation doesn't work... I would expect that the Error("test") would be shown...验证不起作用......我希望Error("test")会被显示......

Does someone has a working example(Java or Kotlin)?有人有工作示例(Java 或 Kotlin)吗?

UPDATE更新

Here is a repository so it can be reproducted: https://github.com/jwz104/webflux-validation-test这是一个可以复制的存储库: https : //github.com/jwz104/webflux-validation-test

Request:要求:

curl --request POST \
  --url http://localhost:8080/tickets \
  --header 'content-type: application/json' \
  --data '{
    "email": "",
    "name": "",
    "message": ""
}'

Renamed contact to ticket, but everything is still the same.将联系人重命名为票证,但一切仍然相同。

The annotations you have placed in the example project are actually annotations on the constructor parameters of the Ticket class.您在示例项目中放置的注释实际上是对Ticket类的构造函数参数的注释。 For Spring validation, you need to annotate the fields instead.对于 Spring 验证,您需要对字段进行注释。 You can do this in Kotlin by using annotation use-site targets .您可以在 Kotlin 中使用注解 use-site targets来做到这一点。

In this specific case, your Ticket class should look like this:在这种特定情况下,您的 Ticket 类应如下所示:

data class Ticket(
        @field:Id
        @field:JsonSerialize(using = ToStringSerializer::class)
        val id: ObjectId = ObjectId.get(),

        @field:Email
        @field:Max(200)
        @field:NotEmpty
        val email: String,

        @field:NotEmpty
        @field:Size(min = 2, max = 200)
        val name: String,

        @field:NotEmpty
        @field:Size(min = 10, max = 2000)
        val message: String
)

This, along with the following controller function will work and return errors as expected:这与以下控制器功能一起将按预期工作并返回错误:

@PostMapping("tickets")
fun create(@RequestBody @Valid contact: Mono<Ticket>) : Mono<Ticket> {
    return contact.flatMap { ticketRepository.save(it) }
            .doOnError{ Error("test") }
}

I had to combine few of the answers from SO to get the validation correct.我不得不结合 SO 中的几个答案才能得到正确的验证。 What I did was:我所做的是:

  • Made my data class as suggested here .按照此处的建议制作我的数据类。

    • Then i used javax.validation.Validator class to validate the data class.然后我使用javax.validation.Validator类来验证数据类。

import javax.validation.Validator import javax.validation.ConstraintViolationException

@Service
open class MyService {
    @Autowired
    lateinit var repository: UserRepository

    @Autowired
    lateinit var validator: Validator

     open fun createUser(user: User): Mono<User> {
         val violations = validator.validate(user)
          //if it violates our constraints, it will throw an exception, which we 
          //handle using global exception handler
          if(violations.isNotEmpty()){
               throw ConstraintViolationException(violations)
           }
           return repo.save(user)
         }
. . .
}
  • Add these lines in application.properties.在 application.properties 中添加这些行。
 spring.mvc.throw-exception-if-no-handler-found=true spring.resources.add-mappings=false

And to catch the exceptions.并捕获异常。

@RestControllerAdvice    
open class ExceptionHandlers {

  @ExceptionHandler(ConstraintViolationException::class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  fun throwConstraintViolationExcetion(ex: ConstraintViolationException): ApiResponse {
    return ApiResponse (message= ex.message.toString(), data= null);
  }
}

ps ApiResponse is just a data class that takes server message & data as parameters. ps ApiResponse只是一个以服务器消息和数据为参数的数据类。 No need to handle errors in @Controller as it will be thrown by the @Service class无需处理@Controller错误,因为它会被@Service类抛出

You need to also add bindingResult: BindingResult to as an extra parameter.您还需要添加bindingResult: BindingResult作为额外参数。 When the method begins you can do something like bindingResult.isValid() .当方法开始时,您可以执行诸如bindingResult.isValid() We use an aspect over all controller methods to return an error message with the validation errors to the user.我们在所有控制器方法上使用一个方面来向用户返回带有验证错误的错误消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM