【问题标题】:Spring boot, how to use @Valid with List<T>Spring Boot,如何将@Valid 与 List<T> 一起使用
【发布时间】:2016-09-06 11:43:21
【问题描述】:

我正在尝试对 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&lt;Status&gt; statuses 时,它不起作用。

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

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

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

【问题讨论】:

    标签: java spring spring-mvc bean-validation


    【解决方案1】:

    我的直接建议是将 List 包装在另一个 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
    

    不过我没试过。

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

    【讨论】:

      【解决方案2】:

      只需用@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;
          }
      }
      

      【讨论】:

      • 仅添加 @Validated 注释不适用于 List
      【解决方案3】:
      @RestController
      @Validated
      @RequestMapping("/products")
          public class ProductController {
              @PostMapping
              @Validated(MyGroup.class)
              public ResponseEntity<List<Product>> createProducts(
                  @RequestBody List<@Valid Product> products
              ) throws Exception {
                  ....
              }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-09-02
        • 1970-01-01
        • 2020-11-02
        • 2021-01-02
        • 2020-03-09
        • 2020-12-29
        • 2022-01-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多