一、JSR303/JSR-349,hibernate validation,spring validation,dubbo validation 之间的关系
数据的校验是交互式网站一个不可或缺的功能,前端的 js 校验可以涵盖大部分的校验职责,如用户名唯一性,生日格式,邮箱格式校验等等常用的校验。但是为了避免用户绕过浏览器,使用 http 工具直接向后端请求一些违法数据,服务端的数据校验也是必要的,可以防止脏数据落到数据库中,如果数据库中出现一个非法的邮箱格式,也会让运维人员头疼不已。我在之前保险产品研发过程中,系统对数据校验要求比较严格且追求可变性及效率,曾使用 drools 作为规则引擎,兼任了校验的功能。而在一般的应用,可以使用本文将要介绍的 validation 来对数据进行校验。
简述 JSR303/JSR-349,hibernate validation,spring validation 之间的关系。JSR303 是一项标准,JSR-349 是其的升级版本,添加了一些新特性,他们规定一些校验规范即校验注解,如 @Null,@NotNull,@Pattern,他们位于 javax.validation.constraints 包下,只提供规范不提供实现。而 hibernate validation 是对这个规范的实践(不要将 hibernate 和数据库 orm 框架联系在一起),他提供了相应的实现,并增加了一些其他校验注解,如 @Email,@Length,@Range 等等,他们位于 org.hibernate.validator.constraints 包下。而万能的 spring 为了给开发者提供便捷,对 hibernate validation 进行了二次封装,显示校验 validated bean 时,你可以使用 spring validation 或者 hibernate validation,而 spring validation 另一个特性,便是其在 springmvc 模块中添加了自动校验,并将校验信息封装进了特定的类中。这无疑便捷了我们的 web 开发。本文主要介绍在 springmvc 中自动校验的机制。
二、spring validation
2.1 使用
- 我们只需要引入 spring-boot-starter-web 依赖即可,如果查看其子依赖,可以发现如下的依赖:
2) 使用注解并使用@Validated 开启校验
3)@Valid和@Validated区别
2.2 原理
在spring-mvc中,RequestResponseBodyMethodProcessor是用于解析@RequestBody标注的参数以及处理@ResponseBody标注方法的返回值的。显然,执行参数校验的逻辑肯定就在解析参数的方法resolveArgument()中:
可以看到,resolveArgument()调用了validateIfApplicable()进行参数校验。
看到这里,明白为什么这种场景下@Validated、@Valid两个注解可以混用。我们接下来继续看WebDataBinder.validate()实现。最终发现底层最终还是调用了Hibernate Validator进行真正的校验处理。
实际上,不管是requestBody参数校验还是方法级别的校验,最终都是调用Hibernate Validator执行校验,Spring Validation只是做了一层封装。
springboot在WebMvcAutoConfiguration 自动引入了validator的bean,这个bean最终会被RequestResponseBodyMethodProcessor引用并用作校验参数。
参考:Spring Validation最佳实践及其实现原理,参数校验没那么简单!
三、dubbo validation
3.1 使用
参数验证功能 是基于 JSR303 实现的,用户只需标识 JSR303 标准的验证 annotation,并通过声明 filter 来实现验证 。
<dubbo:reference id="validationService" interface="org.apache.dubbo.examples.validation.api.ValidationService" validation="true" />
只要在dubbo注册时配置validation = true。 并在参数上使用 JSR303 标准的验证 annotation 就可以生效了
3.2 原理
dubbo启用参数验证要依赖hiberate-validator包,最终底层八成也是调用Hibernate Validator执行校验
参考:在 Dubbo 中进行参数验证