本文主要介绍fluent规格方法(fluent未赋值变量),下面一起看看fluent规格方法(fluent未赋值变量)相关资讯。
fluent-validator business checker背景在互联网行业,基于java开发的业务系统的业务逻辑代码往往更新非常频繁,无论服务器还是客户端,这是由于功能的快速迭代。一般的公司,尤其是用java web技术搭建的平台,无论是基于模块化还是基于服务,业务逻辑都会相对复杂。这些系统之间和内部往往存在大量的api接口,这些接口一般需要检查输入参数(缩写为input parameters),以确保:1)核心业务逻辑能够按预期顺利执行。2)数据可以正常访问。3)数据安全。包括遵守约束和限制、访问控制和无sql注入。在维护核心业务逻辑的同时,开发人员还需要对输入做严格的验证。当输入不合法时,它可以给呼叫者一个明确的反馈。最常见的反馈是返回封装结果的对象或抛出异常。一些常见的验证码片段如下:
公共响应execute(request request){ if(request = = null){ throw biz exception;} list cars = request . get cars;if(collection utils . isempty(cars)){ throw biz exception;} for (car汽车:汽车){ if(car . getseatcount2){ throw biz exception;}} //做核心业务逻辑}我们可以发现它不够优雅,违背了一些范式:1)违背了单一责任原则。核心业务逻辑和验证逻辑耦合在一个类中。2)开/关原则(开/关)。我们应该对扩展持开放态度,对修改持封闭态度,验证逻辑不容易扩展,一旦需要修改,就需要动整个类。3)唐 不要重复。代码冗余,同样的逻辑可能分散在很多地方,长期来看不容易收集。
1.简介fluentvalidato是一个合适的用java语言开发的程序让开发人员重新专注于业务逻辑,并使用流畅的接口调用风格使验证运行得更优雅。同时,验证器可以以开放封闭的原则,实现可最大程度重用的工具库。
2.特征验证逻辑和业务逻辑不再耦合,摒弃了原来不规则验证逻辑分散的现象。验证器各司其职,易于维护,可以重用。一个可扩展的验证器只负责某个属性或对象的验证,可以职责单一,易于维护,可重用。fluent接口调用可以通过注释验证用属性修饰,这样可以减少硬编码的数量。支持jsr 303-bean验证标准。也许你已经使用了hibernate验证器。你不 我不必放弃它。fluentvalidator可以站在巨人的肩膀上。spring good集成检查器可以由spring ioc容器托管。您可以直接使用注释来验证参数,并配置拦截器。核心业务逻辑完全没有验证逻辑的影子,干净利落。回调给你充分的自由来验证过程中发生的错误和异常,以及验证结果的返回,开发者可以定制。3.入门3.1介绍maven依赖:依赖groupidcom.baidu.unbiz/groupid工件id fluent-validator/工件id exclusions groupid org . slf4j/groupid工件id slf4j-log4j 12/工件id/exclusion/排除版本1 . 0 . 5/版本/依赖3.2广义的业务域模型,dto(数据传输对象),vo(值对象),bo(业务对象),pojo等。都可以算是商业表达模式。创建一个学生班级,包括姓名、年龄、学校名称和地区。
包com . example . fluent validator;进口龙目岛。allargsconstructor进口龙目岛。数据;/* * * * @作者: jianyul * @日期:2022/5/16 18 : 00 */@ data @ allargsconstructorpublic class studentd to { private string name;私有整数年龄;私串校名;私有字符串区;}3.3验证器示例为学校名称创建一个验证器,代码如下:
公共类schoolnamevalidator扩展validatorhandlerstring实现validatorstring { @ override public boolean validate(validator context,string schoolname) { if(! 无锡中学。equals(学校名称)){context。添加错误消息( 学校名称不正确);返回false}返回true} } it 实现验证器接口非常简单。generic t指定这个验证器要验证的对象的类型。继承validatorhandler可以避免实现一些默认方法。validate方法的第一个参数是整个验证过程的上下文,第二个参数是要验证的对象,即学校名称。验证逻辑:假设学校名称必须是无锡中学,否则会在上下文中放一个错误信息并返回false,成功返回true。
3.4验证studentdto studentdto =新studentdto( 张三 ,18,和苏州中学, 无锡 );result result = fluent validator . check all。on(studentdto.getschoolname,new schoolnamevalidator)。dovalidate。result(to simple);system.out.println(结果);//打印结果:result {issuccess = false,errors =[不正确的学校名称]}首先我们通过fluentvalidator.checkall获取了一个fluentvali。dator实例,然后调用failfast意味着如果有错误,它会立即返回,它的反义词是failover。然后,对的操作意味着使用相应的检查器来检查指定的属性。到目前为止,真正的检查还没有完成,也就是所谓的 懒惰估价 。it 这有点像java8 stream api中的filter和map方法,它们直到dovalidate被验证后才真正实现。最后我们需要收集一个结果供调用者打印,直接使用默认提供的静态方法tosimple做一个回调函数,传入result方法,最后返回结果类。
4.了解关于4.1验证器的更多信息。如下解释验证器接口代码:
公共接口validatort {/** *判断是否接受或需要对对象* p/ *进行验证,如果返回true,则调用{ @ link # validate(validator context,object)}。否则跳过验证器* * @param context验证上下文* @param t要验证的对象是否* * @return已验证*/boolean accept(验证器上下文,t t);/* * *如果出现错误,需要通过内部调用{ @ linkvalidatorcontext # add error msg(string)}方法添加错误,即codecontext,则执行验证* p/ *adderrormsg (string) */code,错误将被添加到结果存根{@link result}的错误消息列表中。* * @param context验证上下文* @param t要验证的对象是否* * @return由*/boolean validate验证(验证器上下文,t t);/* * *异常回调* p/ *执行{@ link # accept(验证器上下文,对象)}或{@ link # validate(验证器上下文,对象)} * * @param e exception * @param上下文验证上下文* @param t要验证的对象*/ voidone exception(exception e,validatorcontext上下文,t t);}validatorhandler是一个实现验证器接口的模板类。如果你自己的验证器没有。;如果不想覆盖以上三个方法,可以继承这个validatorhandler。
公共类validatorhandlert实现validator t { @ override public boolean accept(validator context context,t t){ return true;} @ override public boolean validate(validator context,t t){ return true;} @ override public void on exception(exception e,validator context,t t) {}当内部检查逻辑出现错误时,有两种处理。首先,它很简单,如上面3.3中的代码所示:context . adderrormsg( 学校的名字是不正确的);第二,你需要详细的信息,包括错误消息、错误属性/字段、错误值和错误代码,这些都可以自己定义。放置错误的方法如下:create方法传递消息(必选),seterrorcode方法设置错误代码(可选),setfield设置错误字段(可选),setinvalidvalue设置错误值。当然,您需要result(tocomplex)来获取这些信息。
公共类区域验证器扩展验证器句柄字符串实现验证器字符串{//实现验证器接口。generic t指定该checker @ override public boolean validate(验证器上下文,字符串区域)要验证的对象的类型{if(! 无锡 。等于(面积)){上下文。添加错误(validationerror。创建( 地址不正确).seterrorcode(5000) .setfield( 面积和面积) .setinvalidvalue(area));//context . adderrormsg( 地址不正确);返回false}返回true}}如果需要,可以使用complexresult,它包含错误消息、错误属性/字段、错误值和错误代码,如下图:
complex result ret = fluent validator . check all。故障转移。on(studentdto.getarea,new areavalidator)。dovalidate。result(to complex);system . out . println(ret);//打印结果:result {issuccess = false,errors =[validation error { error code = 5000,errormsg = 地址不正确。;,field = 面积和面积。;,invalidvalue= suzhou}],timeelapsedinmillis=1}以上都是用来写单个属性值对应的验证器代码。在实际开发中,我们需要对整个对象的多个属性进行业务验证。这时,我们可以为整个对象编写相应的验证器,最后使用complexresult接收验证结果。代码如下:
公共类studentvalidator扩展validatorhandlerstudentdto实现validatorstudentdto { @ override public boolean validate(validator context,studentdto studentdto) { if(! 无锡 。等于(studentdto。getarea ) {context。添加错误(validationerror。创建( 地址不正确).seterrorcode (5000)。setfield( 面积和面积).setinvalid值(studentdto。getarea));}如果(! 无锡中学。等于(studentdto。getschoolname )) {context。添加错误(validation error . create( 学校名称不正确).seterrorcode (5000)。setfield( 校名 ).setinvalid值(studentdto。get school name));}//检查是否有错误信息if (collection utils。不为空(上下文。result . get errors)){返回false}返回true对上的} }的一系列调用实际上是在构建一个调用链,所以传入一个调用链是很自然的。
validator chain chain = new validator chain;list validator validators = new arraylist validator;validators . add(new student validator);chain.setvalidators(验证器);complex result rets = fluent validator . check all。on(studentdto,chain)。dovalidate。result(to complex);system . out . println(rets);//打印结果:result {issuccess = false,errors =[validation error { error code = 5000,errormsg = 地址不正确。;,field = 面积和面积。;,invalidvalue= suzhou},验证错误{错误代码= 5000,错误消息= 学校名称不正确。;,field = 学校名称及名称。;,无效值=苏州中学}],timeelapsedinmillis=7}展开。
可以根据项目自定义返回结果类型,实现resultcollector。
公共接口结果收集器t {/* * *转换为外部结果* * @param result框架内部验证结果* * @将外部验证结果对象*/t返回给result(验证结果结果);} 4.2 oneach如果您想验证是一个集合或数组,那么您可以使用oneach,flu:。
complex result result = fluent validator . check all。oneach(list,new studentvalidator)。dovalidate。result(to complex);4.3验证失败时fail fast或fail over,即验证器的validate方法返回false,那么是继续还是直接退出?默认情况下使用failfast方法并直接退出。如果您想继续完成所有检查,请使用故障切换跳过。
complex result result 1 = fluent validator . check all。failfast。on(lis.getarea,new areavalidator)。on(lis.getschoolname,new schoolnamevalidator)。dovalidate。result(to complex);complex result result 2 = fluent validator . check all。故障转移。on(lis.getarea,new areavalidator)。on(lis.getschoolname,new schoolnamevalidator)。dovalidate。result(to complex);4.4 whenon后面可以跟when。当满足上的表达式时,启用验证,否则跳过调用。
complex result result = fluent validator . check all。故障转移。on(lis.getarea,new areavalidator)。当( 20 。equals(lis.getage))。on(lis.getschoolname,new schoolnamevalidator)。dovalidate。结果(tocomplex);system.out.println(结果);4.5验证回调callbackdovalidate方法接受validatecallback接口。
公共接口验证回调{/* * *所有验证完成并成功后,* @ param validateorelementlist验证器列表*/void on success(validateorelementlist);/* * *所有验证步骤完成后,发现验证过程中存在* * @ param validatorelementlist * @ param errors */void on fail(list validation errors);/* * *验证过程中发生异常后,* * * @ param validator * @ param e exception * @ param target正在验证对象* * @ throws exception */voidonaughtexception(validator,exception e,object target)throws exception;}我们可以根据业务需求在验证回调接口中进行其他逻辑处理,如下图:
fluentvalidator.checkall。on(lis.getschoolname,new schoolnamevalidator)。do validate(new defaultvalidatecallback{ @ override public void on success(validatorelementlist validatorelementlist){ system。out . println( 验证成功);} @ override public void on fail(validatorelementlist validatorelementlist,listvalidationerror errors){ system . outprintln( 验证失败);} }) .result(to complex);4.6 runtimevalidateexception如果验证中出现一些不可控的异常,比如数据库调用失败、rpc连接失败等。,将会引发一些异常。如果验证器没有try-catch处理,fluentvalidator会将这些异常封装在runtimevalidateexception中,然后重新抛出。
4.7 context通过putattribute2context方法,可以将一些键值对注入到fluentvalidator中,并在所有的validator之间共享,这有时相当有用。
结果结果=流畅验证器。checkall。put attribute 2 context( 学校 , 常州中学).在(列表。getschoolname,new schoolnamevalidator)。dovalidate。result(to simple);您可以通过context.getattribute在验证器中获取该值。
string name = context . get attribute( 学校 ,string . class);如果(!姓名。equals(学校名称)){context。adderrormsg( 学校名称不正确);返回false}返回true4.8闭包通过putclosure2context方法,可以将一个闭包注入到fluentvalidator中。这个闭包的功能是在验证器内部调用它,并将结果缓存到闭包中,这样调用者就可以得到上层的结果。一个典型的应用场景是,当一个rpc需要频繁调用时,执行线程内的一次调用往往就足够了,多次调用会影响性能,所以我们可以缓存这个结果,在所有验证器和调用者之间共享。下面显示了caller中有一个getareas方法。如果它需要rpc来获取所有的区域信息,显然是很耗时的。可以在验证器中调用它,然后调用者可以使用闭包来获取后续业务逻辑的结果。
studentdto lis = new studentdto( 李四 ,18,和常州中学, 常州 );closureliststring closure = new closurehandlerliststring{ private liststring all manufacturers;@ override public liststring get result{ return all manufacturers;} @ sneaky trows @ override public void do execute(object...input) {//getarea模拟rpc远程接口调用all manufacturers = getareas;} };fluent validator . check allputclosure 2 context( 面积和面积,关闭)。on(lis.getarea,new areavalidator)。dovalidate。result(to simple);获取验证器中接口查询的数据:
closureliststring closure = context . get closure( 面积和面积);liststring areas = closure . executeandgetresult;如果(!areas . contains(area)){ context . add error(validation error . create( 地址不正确).seterrorcode (5000)。setfield( 面积和面积).setinvalid值(area));返回false}返回true}5.先进的游戏性和hibernate验证集成。
hibernate validator是jsr 303-bean验证规范的最佳实现类库。他只是jboss家族的一员,和著名的hibernate orm有关系,属于远亲。很多框架自然会集成这个优秀的类库。比如spring mvc s @valid注释可以检查控制器方法上的参数。fluentvalidator肯定不会重复早期的轮子,这么好的类库,肯定要用站在巨人肩膀上的策略,整合一下。要了解关于hibernate validator用法的更多信息,请参考这个链接。fluent-validator集成hibernate-validator需要添加依赖项。
依赖关系groupidcom.baidu.unbiz/groupid artifactid fluent-validator-jsr 303/artifactid exclusions exclusions groupid org . slf4j/groupid工件id slf4j-log4j 12/工件id/exclusions/exclusions版本1.0.5/version/dependency 5.1注释验证以上均通过显示的api调用进行验证,fluentvalidator还提供了基于注释配置的简洁来达到同样的效果。@fluentvalidate可以在属性上修饰,它在内部接收class[]数组参数。这些类必须是验证器的子类,也就是说这些验证器是用来依次验证某个属性的。如下,让 让我们将学生转换为类:
@ data @ allargsconstructorpublic class studentdto { @ not null私有字符串名称;私有整数年龄;@ length(max = 5)@ fluent validate({ schoolname validator . class })私有字符串schoolname@ fluent validate({ area validator . class })私有字符串区域;}然后用on或oneach方法来检查,这里就不 不必传入验证器或验证器链。
complex result ret = fluent validator . check all。故障转移。configure(新的simpleregistry)。开(lis)。dovalidate。result(to complex);默认情况下,fluentvalidator使用simpleregistry将尝试从当前类加载器调用class.newinstance方法来创建新的验证器。
5.2分组验证在使用标注验证时,我们会遇到这样的情况。比如有时候我们会为了增加操作验证a/b/c的三个属性,而为了修改操作需要验证b/c/d/e的四个属性。另一个接受的参数是@fluentvalidate批注,也是class[]的数组,只不过这个类可以是开发者随意编写的简单类,不包含。
@ data @ allargsconstructorpublic class studentdto { @ not null私有字符串名称;私有整数年龄;@ length(max = 5)@ fluent validate(value = { school name validator . class },groups = {add.class})私有字符串schoolname@ fluent validate(value = { area validator . class },groups = update.class)私有字符串区域;}那么验证的时候只需要在checkall方法中传入你要验证的组,你只会做选择性的分组验证。例如,在下面的示例中,将只验证区域(区域)。
complex result result = fluent validator . check all(新类?[] {update.class})。开(lis)。dovalidate。result(to complex);5.3级联验证级联验证也称为对象图,是指当一个类嵌套在另一个类中时所做的验证。如下例所示,我们在garage类中有一个carlist (carlist)。您可以在这个car列表属性上使用注释@fluentvalid,表示您需要级联到内部car进行oneach验证。
public class garage { @ fluent validate({ carnotextceedlimitvalidator . class })@ fluent valid private listcar carlist}请注意,两个注释@fluentvalid和@fluentvalidate并不相互。如下图,调用链会先在carlist上验证carnotexceedlimitvalidator,然后遍历carlist验证每辆车的内部厂家、座位数、车牌。
6.springboot 6.1添加依赖项fluent-validator集成spring需要添加依赖项。
依赖groupidcom.baidu.unbiz/groupid artifactid fluent-validator-spring/artifactid version 1 . 0 . 9/version/dependency 6.2注册fluent-validator fluent-validate和spring使用注释来验证参数,这需要借助spring的aop。fluent-validate提供了处理类fluent validateinterface,但是fluent-validate提供的默认验证回调类defaultvalidatecallback不处理验证的失败,所以需要自己实现一个。
@ slf4jpublic类myvalidatecallback扩展defaultvalidatecallback实现validatecallback { @ override public void on success(validateorelementlist){ log . info( 验证成功);super . on success(validatorelementlist);} @ override public void on fail(validateorelementlist validateorelementlist,list validationerrors){ log . info( 验证失败);抛出新的runtimeexception(errors.get(0))。geterrormsg);} @覆盖公共void onuncauthexception(validatorvalidator,exception e,object target)throws exception { log . info( 检查异常和);抛出新的runtime exception(e);}6.3注册ioc,注册fluentvalidateinterceptor拦截器和myvalidatecallback回调方法,最后配置一个aop规则。
@ configuration public class validatecallback config { @ bean public fluentvalidateinterceptor fluentvalidateinterceptor{ fluentvalidateinterceptor fluentvalidateinterceptor = new fluentvalidateinterceptor;fluentvalidateinterceptor . set callback(validatecallback);返回fluentvalidateinterceptor} public myvalidatecallback validatecallback{ return new myvalidatecallback;} @ bean public beannameautoproxycreator beannameautoproxycreator{//使用beannameautoproxycreator创建代理beannameautoproxycreator = new beannameautoproxycreator;//设置创建代理的bean的名称:proxy creator . setbean names( * serviceimpl );proxy creator . set interceptor names( fluentvalidateinterceptor );返回proxycreator}}6.4使用验证为了方便,在studentserviceimpl实现类中增加了参数验证。
@servicepublic类studentserviceimpl实现studentseservice { @ override public int;s业务逻辑验证框架fluent-validator/
欢迎访问约翰尼 的小屋,一个个人博客。
标签:
方法逻辑
了解更多fluent规格方法(fluent未赋值变量)相关内容请关注本站点。
hdd是固态还是机械硬盘,如何看一个硬盘是固态的还是机械的
女生买vivo还是oppo(女生用vivos9还是opporeno5)
台式电脑买哪个牌子的好用,台式电脑什么品牌好
美团商家相册怎么上传店铺环境图片(美团商家相册怎么上传视频)
欧奇p7手机怎么样,钢铁侠p7手机优缺点
fluent specification method(fluent unassigned variable)
ssr连上但是 无网络连接(ssr连接后无法上网)
小熊网络云平台(小熊云商城)
一加2手机怎么备份
win10u盘无法访问拒绝访问怎么办(u盘windows无法访问该磁盘是怎么回事)
英雄联盟lol冠军旗帜怎么显示不出来(英雄联盟lol冠军旗帜怎么显示的)
2020年必玩游戏(2021年游戏推荐)
360手机内存卡怎么放,360手机助手怎么设置安装到sd卡
苹果手机需不需要系统升级(苹果手机到底需不需要更新系统)
电脑boot一键修复有什么用,电脑中的一键恢复有什么功能
这款性价比之王电视盒子多厉害使用泰捷we60c一月总结(泰捷we60c机顶盒可以投屏吗)
iphonex听不到对方说话 对方能听到我说话(苹果x我听不到对方说话)
i5所有cpu型号和参数,i5处理器性能排行榜
如何查找微信已被清空的记录内容(如何查找微信已被清空的记录视频)
中国笔记本电脑十大名牌排名,2023年十大名牌笔记本电脑有哪些