针对以上的场景,本文探讨一下如何优雅地在业务系统中做参数校验,分享构建通用校验模块的一些实践。
二 业内框架 hibernate validator1 简介JSR提供了一套Bean校验规范的API,维护在包javax.validation.constraints下。该规范使用属性或者方法参数或者类上的一套简洁易用的注解来做参数校验。开发者在开发过程中,仅需在需要校验的地方加上形如@NotNull, @NotEmpty , @Email的注解,就可以将参数校验的重任委托给一些第三方校验框架来处理。
引自网络:
JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator。此实现与 Hibernate ORM 没有任何关系。JSR 303 用于对 Java Bean 中的字段的值进行验证。
Spring MVC 3.x 之中也大力支持 JSR-303,可以在控制器中对表单提交的数据方便地验证。
注:可以使用注解的方式进行验证。
接入validation api及hibernate validator后,做普通的参数校验简单到不行:
Hibernate Validator支持了一系列的如非空, 有效邮箱,正则表达式是否匹配等一系列基础校验支持:
@Email@NotNull@Pattern@AssertFalse......而像业务系统中常见的校验,Hibernate Validator是无法支持的,例如校验订单号是否有效,订单上的商品id是否真实有效,这种校验Hibernate也留了口子,可以自行定义注解,同时自行定义校验逻辑后依赖SPI机制注册到Hibernate Validator中即可。
如何自定义业务参数校验API及其校验实现,可以参考官方文档,不再赘述Hibernate Validator的用法。
2 实现原理可以想下如果自己做一套支持JSR303 bean校验规范的校验框架,我们会如何实现。
其实无非是读取class元数据,获取bean类上的所有带有校验注解的属性,在每次需要校验对象的时候,拿到对象对应属性的值来与其上的所有校验注解来执行校验实现逻辑,然后收集所有不通过的信息。
hibernate validator的实现核心原理也是如此:
上图仅展示一些Hibernate validator的核心组件,实际上有非常多的细节,不在此赘述,有兴趣了解全流程的同学可以自行debug一下,并不是非常复杂。
校验的过程:
配置Hibernate Validator,把所有相关的非懒加载的核心组件都进行初始化,依赖java的SPI机制支持自定义validator进行校验,先进行class数据解析,然后获取对应属性的对应validator进行校验, 最后通过MessageInterpolator组件进行校验错误信息的提取。依赖java的ResourceBundle机制支持校验信息多语言。三 优雅实践基于hibernate validator,怎么可以做一些优雅实践呢?
hibernate validator仅是bean校验框架, 可能还需要做一些适配才可以让我们在业务系统开发中,下面分享一下一些开发实践,核心追求的是业务逻辑与参数校验逻辑完全解耦合,常用的业务参数校验逻辑可以在多套业务系统中被复用以及统一维护所有的校验错误信息。
概要图:
RPC与WEB系统部署架构图:
拦截所有请求,可以基于RPC filter和Spring MVC的HandlerInterceptor来实现RPC请求,和HTTP请求的拦截 , 拦截器中使用validator校验参数,失败的话直接设置失败信息,快速返回。统一参数校验包,纯粹的校验API,所有校验以注解形式做抽象,支持简单复用 , 形如@NotNull , @ExistItem , @ExistBarcode的作用于参数上的注解, 这个可以复用JSR校验规范来实现。统一参数校验的实现(validator) ,所有的校验注解对应的校验逻辑实现以统一maven依赖形式提供 , 和校验API一一对应。hibernate validator进行扩展,校验错误信息解析统一维护于配置中心,接入在配置中心可以在运行时动态修改,以本地文件形式存储校验提示信息也并无不可,只是维护起来复杂麻烦。维护简单易用的starter,开箱即用,支持所有业务系统快速接入。一些代码实现(需要自取):
RPC filter ResourceBundle
// 使用自定义的配置中心信息源 初始化validator public static Validator validator; static { HibernateValidatorConfiguration configure = Validation.byProvider(HibernateValidator.class).configure(); ResourceBundleLocator defaultResourceBundleLocator = configure.getDefaultResourceBundleLocator(); ResourceBundleLocator myResourceBundleLocator = new MyResourceBundleLocator(defaultResourceBundleLocator); configure.messageInterpolator( new ResourceBundleMessageInterpolator(myResourceBundleLocator)); configure.enableTraversableResolverResultCache(false); validator = configure.buildValidatorFactory().getValidator();
本文转自网络,原文链接:https://developer.aliyun.com/article/784193
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!
公司介绍 长沙营智信息技术有限公司旗下易撰网,2017年10月份上线以来,基于数据...
【51CTO.com快译】不知道您是否听说过软件架构师最讨厌意大利面这个梗?它是指软...
阿里巴巴、腾讯、支付宝、网易、IBM、谷歌、京东、 百度、滴滴等一线互联网公司...
大家在开发Python的过程中,一定会遇到很多反斜杠的问题,很多人被反斜杠的数量...
案例背景 永安稻香小镇的体验式数字农业基地是余杭街道依托“阿里以西10分钟”的...
人脸识别 是目前商业应用最成熟、最广泛的人工智能技术之一,成为开发者、企业接...
【51CTO.com快译】 数据分析是对数据进行判断、细化、更改和建模的过程,目的是...
操作场景 您可以删除不需要的私有镜像。 删除私有镜像后,将无法找回,请谨慎操...
大数据市场如今正在呈爆炸式增长。根据调研机构Markets and Markets公司的调查,...
本月DataWorks产品月刊为您带来 产品活动 1.参与阿里云DataWorks问卷调研 (Aliyu...