spring Sping Boot @Valid on requestBody in controller方法不工作

eufgjt7s  于 2023-06-28  发布在  Spring
关注(0)|答案(7)|浏览(120)

我尝试在一个由@ Validated注解的@RestController中验证一个由@ Valid注解的简单请求主体。验证在请求中的原始变量上正确工作(在下面的例子中是年龄),但在pojo请求体上不工作。@Valid annotation对请求体Person类没有影响(即控制器接受空白姓名和年龄在18岁以下)。
人员类别:

import javax.validation.constraints.Min
import javax.validation.constraints.NotBlank

class Person (

    @NotBlank
    val name : String,

    @Min(18)
    val age : Int
)

控制器类:

import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import javax.validation.Valid

@RestController
@Validated
class HomeController {

    @GetMapping("/{age}")
    fun verifyAge(@PathVariable("age") @Min(18) age:Int): String {
        return "Eligible age."
    }

    @PostMapping
    fun personValidation(@Valid @RequestBody person : Person) : String {
        return "No validation error"
    }
}

@NotBlank、@Min和@Valid注解来自以下依赖关系:

implementation("org.springframework.boot:spring-boot-starter-validation:2.3.0.RELEASE")

如何使@Valid在@Validated控制器中的Person请求体上工作?

iyr7buue

iyr7buue1#

不要将Person标记为Spring @Component。
实现字段验证的正确方法是在属性中添加@field。示例代码:

class SomeRequest(
    @field:NotBlank val name: String
)

这是因为Sping Boot 需要将此注解应用于字段。Kotlin默认将它们应用于构造函数参数。请参阅Kotlin文档中的Annotation use-site targets。

e3bfsja2

e3bfsja22#

在我的例子中,为了让@Valid @RequestBody在springboot应用程序中工作,必须使用这两个依赖项

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>
p4rjhz4m

p4rjhz4m3#

[编辑]这对我也有效(在构造函数参数上添加字段注解),正如一位用户所回答的那样:

import javax.validation.constraints.Min
import javax.validation.constraints.NotBlank

class Person (

    @field:NotBlank
    val name : String,

    @field:Min(18)
    val age : Int
)

虽然将Person的“Kotlin”类定义更改为如下(构造函数参数改为无参数)(注意括号(...)改为花括号{...}),但在不添加@field注解的情况下也可以工作:

import javax.validation.constraints.Min
import javax.validation.constraints.NotBlank

class Person {

    @NotBlank
    lateinit var name: String

    @Min(18)
    var age: Int = 0
}
7qhs6swi

7qhs6swi4#

以防有人使用@BasePathAwareController@RepositoryRestController注解。@RepositoryRestController@BasePathAwareController目前不支持@Valid
Spring Data REST中有一个开放的问题:https://github.com/spring-projects/spring-data-rest/issues/967

xmd2e60i

xmd2e60i5#

您可以尝试此选项。
请使用@PostMapping(“/validateBody”)这样的URLMap@PostMapping,并尝试使用其URL。与https://reflectoring.io/bean-validation-with-spring-boot/上的操作相同

mctunoxg

mctunoxg6#

Piotr Solarski是正确的(上面),向请求体添加组件是不正确的,因为主体会发生变化,并且为它创建单个对象可能会变得棘手(即使它解决了OP的问题)。
在一个MVC应用程序中,这就是我的错误所在。
我添加了你做过的常用的东西(pom中的库,@Valid on RequestBody等)
Spring文档(和许多博客)留下的微妙之处在于Spring会寻找一个退出点来抛出错误,但如果该退出不存在,它将返回404。在阅读了大量内容之后,特别是blog,添加这个类让Spring识别@Valid并找到一个抛出错误的出口点

@RestControllerAdvice
    @Order(1) 
    public class RestControllerExceptionHandler {

    @RequestMapping(value = { "error/404" }, method = RequestMethod.GET)
    @ExceptionHandler(Exception.class)
    public String handleUnexpectedException(Exception e) {
        return "views/base/rest-error";         
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String handlemethodArgumentNotValid(MethodArgumentNotValidException exception) { //
        // TODO you can choose to return your custom object here, which will then get transformed to json/xml etc.
        return "Sorry, that was not quite right: " + exception.getMessage();
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ConstraintViolationException.class)
    public String handleConstraintViolation(ConstraintViolationException exception) { //
        // TODO you can choose to return your custom object here, which will then get transformed to json/xml etc.
        return "Sorry, that was not quite right: " + exception.getMessage();
    }

    
}
ecfdbz9o

ecfdbz9o7#

请将此依赖项添加到pom.xml文件中。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

相关问题