为什么Spring Boot为Controller方法参数验证抛出不同的异常?

时间:2019-06-05 21:02:07

标签: spring-boot

在使用约束验证批注(@ Min,@ NotNull等)验证原始类型或等效类型(整数,布尔值)时,Spring Boot抛出ConstraintViolationException。但是,当使用@Valid批注验证参数时,则会抛出MethodArgumentNotValidException

我有一个用@ControllerAdvice注释的类来处理控制器中的异常。 问题是,根据spring-boot-starter-parent版本,结果相差很大。 使用版本2.0.5.RELEASE时,我只需要包含ConstraintViolationException类的处理程序。 但是还有其他一些版本也会抛出MethodArgumentNotValidException

它已经在GitHub issue上被提及,但没有有用的答案...

我将在这里使用lukasniemeier-zalando的示例。有关更多详细信息,请单击上面的链接。

 @Validated  // needed to actually trigger validation
 @RestController
 class MyController {

   @RequestMapping
   Response serve(
     @RequestParam @Min(2) Integer parameter,  // throws ConstraintViolationException
     @RequestBody @Valid BodyModel body        // throws MethodArgumentNotValidException
     ) {
       return new Response();
     }

 }

我希望两个验证都抛出相同的异常,无论它们是哪一个,都是为了保持一致。

显然,没有理由让它如此,至少这是我从其他GitHub issue那里了解到的。

然后我只想回答一个问题,为什么Spring Boot抛出两种异常来表示相同的问题(参数验证)。

注意:如前所述,使用2.0.5.RELEASE版本spring-boot-starter-parent不会发生。

<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>

但是,正如我所链接的上一个GitHub问题所报告的那样,版本2.0.0.M4具有这种行为,而我在2.2.0.M3版本中也遇到了这种情况。

2 个答案:

答案 0 :(得分:1)

它们由不同的验证机制处理。类上的@ValidatedMethodValidationInterceptor处理,这是用于类的通用验证机制。因此,它引发了ConstraintViolationException。之所以在这里使用@Validated只是因为类型上不允许使用@Valid注释。因此,启用/触发MethodValidationInterceptor的唯一方法是使用@Validation批注。

控制器中方法参数上的@ValidModelAttributeMethodProcessor内部处理,并导致特定于网络的绑定异常,即MethodArgumentNotValidException。在准备方法调用时,RequestMappingHandlerAdapter会间接地调用ModelAttributeMethodProcessor。除了@Valid之外,您还可以在方法参数上使用@Validated批注。 Spring MVC支持这两种方式(实际上甚至在@Validated出现之前就已经支持@Valid!)。

解决方案/解决方法是创建自己的异常处理程序,该异常处理程序与ConstraintViolationException一样处理MethodArgumentNotValidException。您链接到的GitHub问题中也建议使用此方法。

答案 1 :(得分:0)

检查这些文档:

1-https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/MethodArgumentNotValidException.html

2-{{​​3}}

对带有@Valid的参数进行验证失败时,将引发

MethodArgumentNotValidException 异常。

对带有注释的参数进行验证失败时将引发

ConstraintViolationException 异常。