在使用约束验证批注(@ 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
版本中也遇到了这种情况。
答案 0 :(得分:1)
它们由不同的验证机制处理。类上的@Validated
由MethodValidationInterceptor
处理,这是用于类的通用验证机制。因此,它引发了ConstraintViolationException
。之所以在这里使用@Validated
只是因为类型上不允许使用@Valid
注释。因此,启用/触发MethodValidationInterceptor
的唯一方法是使用@Validation
批注。
控制器中方法参数上的@Valid
由ModelAttributeMethodProcessor
内部处理,并导致特定于网络的绑定异常,即MethodArgumentNotValidException
。在准备方法调用时,RequestMappingHandlerAdapter
会间接地调用ModelAttributeMethodProcessor
。除了@Valid
之外,您还可以在方法参数上使用@Validated
批注。 Spring MVC支持这两种方式(实际上甚至在@Validated
出现之前就已经支持@Valid
!)。
解决方案/解决方法是创建自己的异常处理程序,该异常处理程序与ConstraintViolationException
一样处理MethodArgumentNotValidException
。您链接到的GitHub问题中也建议使用此方法。
答案 1 :(得分:0)
检查这些文档:
2-{{3}}
对带有@Valid
的参数进行验证失败时,将引发MethodArgumentNotValidException 异常。
对带有注释的参数进行验证失败时将引发ConstraintViolationException 异常。