【问题标题】:How to validate the size of @RequestParam of type List如何验证 List 类型的 @RequestParam 的大小
【发布时间】:2019-08-17 17:21:35
【问题描述】:

我正在创建一个 Spring-Boot 微服务 REST API,它需要 @RequestParam 类型为 List<String>。如何验证列表是否包含最小值和最大值?

到目前为止,我已经尝试使用 @Size(min=1, max=2),它应该也支持集合 (javax.validation.constraints.Size)。

我还尝试添加@ValidBindingResult 参数以及@Size 注释,但没有成功。

我更喜欢使用类似于使用@Size(min=1, max=2) 的第一个示例的解决方案,它更紧凑和整洁。这是针对 Spring-Boot 2.1.2.RELEASE 的。

@RestController
public class MyApi {

    @GetMapping(value = "/myApi", produces = { APPLICATION_JSON_VALUE })
    public ResponseEntity<List<MyObject>> getSomething(@Valid @RequestParam(value = "programEndTime", required = false) @Size(min = 1, max = 2) List<String> programEndTime, BindingResult result) {
        if (result.hasErrors()) {
            System.out.println("Error");
        } else {
            System.out.println("OK");
        }
    }
}

我希望到达System.out.println("Error") 行,但实际上已跳过。

【问题讨论】:

  • 您的约束是一个逻辑错误,@RequestParam(required=false)@Size(min=1) 放在一起没有意义。
  • 当然可以。一方面这不是强制性参数,但另一方面,如果提供,它应该遵守大小限制。

标签: java spring-boot spring-web spring-validator


【解决方案1】:

根据 Bean Validator 2.0、Hibernate Validator 6.x,您可以直接对参数化类型使用约束。

@GetMapping(path = "/myApi", produces = { APPLICATION_JSON_VALUE })
public ResponseEntity<List<MyObject>> getSomething(@RequestParam(value = "programEndTime", required = false) List<@Size(min = 1, max = 2) String> programEndTimes)

欲了解更多信息,请查看Container element constraints

【讨论】:

    【解决方案2】:

    如果您使用方法参数验证,您应该使用 @Validated 注释您的控制器,如 the documentation 所述:

    为了符合 Spring 驱动的方法验证的条件,所有目标类都需要使用 Spring 的 @Validated 注释进行注释。 (可选地,您还可以声明要使用的验证组。)有关 Hibernate Validator 和 Bean Validation 1.1 提供程序的设置详细信息,请参阅MethodValidationPostProcessor javadoc。

    这意味着您应该将代码更改为:

    @Validated // Add this
    @RestController
    public class MyApi {
        // ...
    }
    

    之后,如果验证不匹配,它将抛出ContraintViolationException

    但请注意,由于您只有一个 @Size() 注释,因此如果您不提供 programEndTime,则该集合将是 null,这也是有效的。如果你不想要这个,你也应该添加一个@NotNull 注释,或者从@RequestParam 中删除required = false 值。

    您不能使用BindingResult 来检索错误,因为它仅适用于模型属性或请求正文。你可以做的是为ConstraintViolationException定义一个异常处理程序:

    @ExceptionHandler(ConstraintViolationException.class)
    public void handleConstraint(ConstraintViolationException ex) {
        System.out.println("Error");
    }
    

    【讨论】:

    • 谢谢。但是,恐怕它仍然不起作用。我按照建议在类上添加了“已验证”注释。是否需要在某处定义 MethodValidationPostProcessor bean?或者也许我错过了其他东西?
    • @Nel 不,这应该可以。 MethodValidationPostProcessor bean 由 Spring boot 自动创建。实际上,我自己测试了这段代码,只要我访问http://localhost:8080/myApi?programEndTime 或访问http://localhost:8080/myApi?programEndTime=A&amp;programEndTime=B&amp;programEndTime=C,验证就会启动。如果它对您不起作用,请确保在您的问题中列出您的依赖项。由于类路径中缺少类,可能没有创建必要的 bean。
    • 由于我添加了 MethodValidationPostProcessor bean,它起初不起作用。删除后验证成功。
    【解决方案3】:

    可以使用Class和@RequestBody进行参数验证,和我一样成功。

    public class Test {
        @Size(min = 1 , max = 5)
        private List<String> programEndTime;
    
        public List<String> getProgramEndTime() {
            return programEndTime;
        }
    
        public void setProgramEndTime(List<String> programEndTime) {
            this.programEndTime = programEndTime;
        }
    }
    
        @PostMapping("test")
        public void test( @Valid   @RequestBody Test test,
                         BindingResult result){
            if (result.hasErrors()) {
                System.out.println("Error");
            } else {
                System.out.println("OK");
            }
            System.out.println(",.,.");
        }
    

    【讨论】:

      猜你喜欢
      • 2017-10-21
      • 2011-11-16
      • 1970-01-01
      • 2022-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多