竹笋

首页 » 问答 » 灌水 » SpringMvcValidated注
TUhjnbcbe - 2023/10/10 17:11:00

1

0

Validated和

valid的对比

SpringValidation验证框架对参数的验证机制提供了

Validated(SpringsJSR-规范,是标准JSR-的一个变种),javax提供了

Valid(标准JSR-规范),配合BindingResult可以直接提供参数验证结果。

在检验Controller的入参是否符合规范时,使用

Validated或者

Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个有所不同。

1

1分组

Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,可参考高效使用hibernate-validator校验框架。

Valid:作为标准JSR-规范,不支持分组的功能。

1

2注解地方

Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上。

Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上。

两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。

2

0SpringMvc接口参数校验原理

springmvc接口方法中注有

Validated或

Valid参数是如何校验的呢?怎么就能把参数绑定之后的校验结果给到BindingResult实例呢?

其实如果你对springmvc的方法参数解析器(HandlerMethodArgumentResolver)了解一些,就应该知道参数校验这块肯定是在对应的方法参数解析器里执行的。如下是

RequestBody注解对应的参数解析器(RequestResponseBodyMethodProcessor)。

直接定位到resolveArgument这个方法,很明显,该方法是根据参数类型找到支持的消息转换器(MessageConverter),然后从requestbody中读取信息,最后转换成对应的参数实体。

WebDataBinder主要是完成对象属性校验的。如果你熟悉

ModelAttribute注解对应的方法参数解析器(ModelAttributeMethodProcessor),是先通过WebDataBinder进行入参属性绑定,然后再进行校验。

注意,本文的重点代码来了。

简单说一下validateIfApplicable方法的逻辑,遍历当前参数methodParam所有的注解,如果注解是

Validated或注解的名字以‘Valid’开头,则使用WebDataBinder对象执行校验逻辑。

isBindExceptionRequired方法,说得通俗一点,就是要不要抛出异常。怎么判断呢?如果当前参数后面还有参数并且参数类型是Erros(BindingResult继承Erros)则抛出异常。

最后会把BindingResult结果放到ModelAndViewContainer对象中保存起来,记住BindingResult.MODEL_KEY_PREFIX这个keyprefix。

mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX+name,binder.getBindingResult());

都说到这里了,BindingResult结果也已经拿到了,该怎么传递给方法中参数呢?会不会有BindingResult参数类型的参数解析器呢?咦,还真他娘的有呀……

看到ErrorsMethodArgumentResolver这个参数解析器的注释和源码,的确是针对BindingResult这种参数类型的。BindingResult.MODEL_KEY_PREFIX这个常量在这里出现了,在ModelAndViewContainer对象中拿到BindingResult对象。注意最后面抛出了一个IllegalStateException异常,也就是在ModelAndViewContainer对象中没有找到BindingResult对象的时候才会抛出这个异常,什么情况找不到?

上述写法就会出现IllegalStateException异常。因为springmvc解析参数的时候是按照顺序,所以BindingResult类型的参数一定要放在校验实体的后面。

3

0

Validated方法级校验

注意:方法级别的入参有可能是各种平铺的参数、也可能是一个或者多个对象。

下面这个例子就是

Validated注解方法级的校验demo,不过需要配合MethodValidationPostProcessor这个后置处理器使用,需要我们手动注册一下。

简单说一下MethodValidationPostProcessor。

validatedAnnotationType变量默认是就是

Validated注解类型,所以创建的切面Pointcut对象是切入所有注有

Validated注解的类的所有方法。

Spring环境里创建动态代理核心指定一个或多个advisor,advisor由pointcut和advice组成,pointcut已经创建,advice实例即MethodValidationInterceptor。很明显,MethodValidationInterceptor专门用于处理方法级别的数据校验,包括入参校验和出参校验,本文就不详细说明了,感兴趣的可以直接参考一下源码。

1
查看完整版本: SpringMvcValidated注