Spring Boot中如何使用@Valid和List<T>?

12

我正在尝试为一个Spring Boot项目添加验证功能。所以我给实体字段添加了 @NotNull 注解。在控制器中,我这样检查它:

我正在尝试为Spring Boot项目添加验证功能。所以我通过在实体的字段上加上 @NotNull 注解来实现。在控制器中,我像这样检查它:

@RequestMapping(value="", method = RequestMethod.POST)
public DataResponse add(@RequestBody @Valid Status status, BindingResult bindingResult) {
    if(bindingResult.hasErrors()) {
        return new DataResponse(false, bindingResult.toString());
    }

    statusService.add(status);

    return  new DataResponse(true, "");
}

这个方法可以工作。但是当我将其使用输入参数 List<Status> statuses 时,它无法工作。

@RequestMapping(value="/bulk", method = RequestMethod.POST)
public List<DataResponse> bulkAdd(@RequestBody @Valid List<Status> statuses, BindingResult bindingResult) {
    // some code here
}

基本上,我想要的是在请求体列表中为每个状态对象应用像add方法中的验证检查。这样,发送方就会知道哪些对象有故障,哪些没有。

如何以简单,快速的方式做到这一点?

4个回答

14

我首先建议将列表包装在另一个POJO bean中,并将其用作请求体参数。

以您的示例为例。

@RequestMapping(value="/bulk", method = RequestMethod.POST)
public List<DataResponse> bulkAdd(@RequestBody @Valid StatusList statusList, BindingResult bindingResult) {
// some code here
}

并且StatusList.java将会被

@Valid
private List<Status> statuses;
//Getter //Setter //Constructors

虽然我没有尝试过。

更新:这个 Stack Overflow 链接中被接受的回答解释了为什么不支持在列表上使用 bean 验证


0

使用 Kotlin 和 Spring Boot Validator

@RestController
@Validated
class ProductController {
    @PostMapping("/bulk")
    fun bulkAdd(
        @Valid
        @RequestBody statuses: List<Status>,
    ): ResponseEntity<DataResponse>> {...}
}

data class Status(
    @field:NotNull
    val status: String
)

0

只需在控制器上标记 @Validated 注释。

它将抛出 ConstraintViolationException,因此您可能希望将其映射到 400: BAD_REQUEST

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice(annotations = Validated.class)
public class ValidatedExceptionHandler {

    @ExceptionHandler
    public ResponseEntity<Object> handle(ConstraintViolationException exception) {

        List<String> errors = exception.getConstraintViolations()
                                       .stream()
                                       .map(this::toString)
                                       .collect(Collectors.toList());

        return new ResponseEntity<>(new ErrorResponseBody(exception.getLocalizedMessage(), errors),
                                    HttpStatus.BAD_REQUEST);
    }

    private String toString(ConstraintViolation<?> violation) {
        return Formatter.format("{} {}: {}",
                                violation.getRootBeanClass().getName(),
                                violation.getPropertyPath(),
                                violation.getMessage());
    }

    public static class ErrorResponseBody {
        private String message;
        private List<String> errors;
    }
}

2
仅仅添加@Validated注解并不能与List<T>一起使用。 - Anto

0
@RestController
@Validated
@RequestMapping("/products")
    public class ProductController {
        @PostMapping
        @Validated(MyGroup.class)
        public ResponseEntity<List<Product>> createProducts(
            @RequestBody List<@Valid Product> products
        ) throws Exception {
            ....
        }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接