java Spring boot,如何在 List<T> 中使用 @Valid

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39348234/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 04:18:19  来源:igfitidea点击:

Spring boot, how to use @Valid with List<T>

javaspringspring-mvcbean-validation

提问by kalahari

I am trying to put validation to a Spring Boot project. So I put @NotNullannotation to Entity fields. In controller I check it like this:

我正在尝试对 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, "");
}

This works. But when I make it with input List<Status> statuses, it doesn't work.

这有效。但是当我用 input 制作它时List<Status> statuses,它不起作用。

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

Basically, what I want is to apply validation check like in the add method to each Status object in the requestbody list. So, the sender will now which objects have fault and which has not.

基本上,我想要的是像在 add 方法中一样对 requestbody 列表中的每个 Status 对象应用验证检查。因此,发送方现在将知道哪些对象有错误,哪些没有。

How can I do this in a simple, fast way?

我怎样才能以简单、快速的方式做到这一点?

回答by Ameen.M

My immediate suggestion is to wrap the List in another POJO bean. And use that as the request body parameter.

我的直接建议是将 List 包装在另一个 POJO bean 中。并将其用作请求正文参数。

In your example.

在你的例子中。

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

and StatusList.java will be

和 StatusList.java 将是

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

I did not try it though.

不过我没有尝试。

Update:The accepted answer in this SO linkgives a good explanation why bean validation are not supported on Lists.

更新:此 SO 链接中接受的答案很好地解释了为什么列表不支持 bean 验证。

回答by Max Farsikov

Just mark controller with @Validatedannotation.

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

It will throw ConstraintViolationException, so probably you will want to map it to 400: BAD_REQUEST:

它会抛出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;
    }
}

回答by Jaroslav Janí?ek

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