通用验证系统commons-validator
1. 前言
本文较详尽地介绍了jakarta开源项目的子项目之一commons-validator(通用验证系统),版本是1.0.2。它使用了一个xml文件来定义针对用户输入的数据验证功能,整个验证体系提供了很强的扩展性,使得开发者可以开发自己的验证函数加入到这个验证体系中来。它对web应用程序提供了客户端javascript验证和服务端验证的两种选择,但是它只是一个验证体系,有些东西还需要自己开发特别是validatoraction的开发,不过有了项目源代码及其例子,还有struts这个优秀的开源项目的示范,使用好commons-validator验证体系应该是挺容易的。本文就这个验证体系作了些探讨,希望对大家有用!
2. 用户问题
我们在开发信息系统时,用户界面往往是一个很容易忽视的但是确是相当重要的地方。我们有好多关于编写后端代码的设计模式,现在我们还拥有commons-validator这样的优秀验证体系对付用户界面的用户千变万化的输入可能。输入验证关乎到整个信息系统的强壮性,因为恶意的输入数据可能导致信息系统崩溃;输入验证还关乎到信息系统的友好性,因为不能给用户提供正确的输入导引经常搞得使用者手足无措,最后只有悲愤而去。
3. 简单分析
通过对上面用户问题的描述,我们可以简单分析一下验证体系的基本特性:
- 验证体系应该具有良好的可扩展性,可以让信息系统开发者开发自己的验证功能,以满足特殊系统的验证要求。
- 验证体系应该能显示准确的验证错误信息,用以帮助使用者纠正错误,而且错误信息应该是外在可配置的,改变相应的错误信息不需要修改源代码。
- 对于web信息系统来说,应该能支持客户端验证和服务端验证两种方式。
4. 使用界面
4.1. 配置文件
下面是验证规则xml文件的元素关系图,我将挑选一些重要而又相对复杂的元素进行讲解。
1. 元素constant
"constant" 元素定义了"field"元素所使用的替换型参数的静态值。 "constant-name" 和 "constant-value" 元素分别表示这个静态值的引用标识和值
2. 元素validator
这个"validator"元素定义了formset元素字段所能使用的 validatoraction对象。
子元素 | javascript | ||||||||||||||||||||||||
属性 |
|
3. 元素formset
"formset" 定义了一个针对locale的 form集. "form"元素定义了有待验证的"field" 集,名字属性是应用程序分配给这个"form"的引用标识。
子元素 | constant form | ||||||||||||
属性 |
|
4. 元素field
"field" 元素定义了需要验证的属性,在web应用中,一个"field"对应于一个HTML 表单控件。验证系统通过验证一个JavaBean来验证这个"field" 元素,这个元素可以接受4个属性:
子元素 | msg arg0 arg1 arg2 arg3 var | |||||||||||||||
属性 |
|
5. 元素msg
"msg" 元素定义了一个定制消息键,用来为验证失败的"field"提供消息文本。 当"field"没有子元素"msg" 元素时,每个validatoraction对象则使用自己的消息属性。
属性 |
|
6. 元素arg0|arg1|arg2|arg3
这是4个参数元素,定义了validator 或field 消息模版中的4个替换值。比如validator的msg对应的消息资源是"必须提供{0}字段,而且字段的长度不能小于{1}字符! ",在显示错误的时候,其中{0}将被arg0的消息文本替换,而{1}将被arg1的消息文本替换。
属性 |
|
7. 元素var
"field"能通过这个元素向某个validatoraction对象传递参数,这些参数也能被arg?元素通过语法${var:var-name}引用。它的子元素var-name和var-value分别为变量标识和变量的值。
4.2. 应用编程接口
如图《Commons-validator的API》所示,commons-validator的类明显的分成三种,第一种为代表验证规则文件中各个元素的类,本文称元素类,第二种是程序准备验证资料和验证的类,本文称fa?ade类,第三种是实现了通用功能的类,本文称工具类。元素类代表了验证规则文件中的各个元素,对于编程者来说主要作用是用他们来得到消息文本;fa?ade类用来使Commons-validator验证系统融入到应用系统中;而工具类有助于编程者写实现各种validatorAction的类。具体的使用参见下面的代码样例。
4.3. 代码样例
虽然common-validation是为web应用写的验证体系,它同时也能用在java应用程序中,为了把注意力放在验证系统的介绍上,下面的验证样例使用java应用程序来表演。
4.3.1. 定义验证规则
验证规则是一个xml文件,定义了需要验证的表单,及其表单的各个字段以及字段的验证要求,另外validator元素是用来完成各个字段的验证要求的。本例定义了一个输入表单nameForm及其两个字段,两个字段都必须提供,而且age字段还必须是整数;还定义了两个验证动作int和required,分别满足整数要求和必须提供的要求:
|
4.3.2. 编写消息资源文件
commons-validator的消息资源包括两大部份,第一部分是包括了参数占位符的validatoraction对象的消息,第二部分是各个输入表单输入数据的显示信息,用作验证失败时的信息显示。本例中值包括了一个输入表单的显示信息:
|
4.3.3. 编写validatorAction
我们从验证定义规则文件中可以看出validator元素定义的int和required validatorAction分别使用了org.i505.validator.MyTypeValidator和org.i505.validator.MyValidator两个类,这个元素还定义了它们使用的验证方法validateInt和validateRequired以及方法的参数类型列表。下面是这两个类的代码:
|
|
4.3.4. 编写javabean
commons-validator是一个针对web应用的输入验证体系,验证规则中的form定义是针对html form表单的,但是common-validator在内部验证时需要javabean。这个javabean的各个属性就代表了html form表单的输入控制。所以针对前面的验证规则,我们实现的javabean需要定义两个属性:age和username,代码如下:
|
注意,这个验证BEAN的age属性的类型是字符串型的,因为它只是代表了html form表单的输入控制的值,原始的用户输入数据基本上都可以用String来表示,如果我们申明age属性的类型时整数型,则我们在html form表单的值到BEAN的age属性就经过了一次类型转换,这个早于我们的整型验证,所以可能有产生类型转换错误的危险。
4.3.5. 编写验证主程序
编写验证主程序主要有下面五步:
- 创建和处理ValidatorResources对象,这要借助于ValidatorResourcesInitializer类利用验证规则定义文件初始化这个对象。
- 创建要验证的bean对象
- 用验证规则定义文件中定义的某个form创建validator对象,并且告诉这个对象要验证的bean对象。
- 运行validator对象的validate()方法实际验证bean对象
- 打印验证结果
下面是依据上面所述步骤编写的实例代码,代码中进行了三次验证,第一次是验证两个属性都是空的bean对象,第二次是age属性不合法的bean对象,第三次是两个属性都合法的bean对象:
|
4.3.6. 打印验证结果
打印验证结果可能是验证体系中最复杂的一部分,因为它涉及到验证文件和消息资源文件,涉及到好多对象以及它们复杂的关系。特别需要指出的是错误消息文本的显示。下面的代码包括三个部分:第一部分是使用资源文件生成ResourceBundle对象,注意你的资源文件必须在classloader能找到的地方;第二部分是实际打印验证结果;第三部分是个显示中文消息的函数。
validator对象的validate()方法会把验证结果保存到其返回的ValidatorResults对象中,它保存了bean对象被验证的每个属性的各种验证要求的验证结果对象ValidatorResult,首先我们可以获取bean对象对应的验证文件定义的form,从而得到相应的消息键和其它信息,而且通过这些信息从ValidatorResults对象中获取相应的ValidatorResult对象,利用ValidatorResult对象isValid函数可以判断验证的成功与否,如果验证没通过,可以使用form的信息显示错误消息文本。
|
验证结果如下:
|
5. 内部剖析
5.1. 类之间的联系
ValidatorResults对象有个map,以field的getKey()为键,这个field的验证结果ValidatorResult对象为值。
ValidatorResult对象也有个map,以field的各个validator元素的名字为键(在field元素的depends中定一个field的validator元素列表),以一个表示验证成功与否的对象为值。
ValidatorResources对象包含一个map,以Locale的某种字符串表示为键,FormSet 为值(所以formset有多种版本),还包含一个map,保存了全局常量,以常量名为键,常量值为值;还包含一个map,以validator元素的name属性为键, validatorAction对象为值。
Formset对象包含一个map,以form的name属性为键,Form对象为值;还包含一个map,以formset元素的子元素Constant的name为键,子元素Constant的值为值。
Form对象包含一个map,以Field元素对应的Field对象的getKey()为键,Field对象为值;另外还拥有一个保存顺序的field对象数组。
field对象拥有一个map,以var的名字为键,var对象为值。
Validator对象包含一个map,以各个validator元素的methodParams参数列表中的名字为键,相应的对象为值,这个map的键和值将会用作调用相应validator元素中的methods属性指定方法的参数。
通过这些map,commons-validator在验证系统各个类间铺了一张类关系表,见下图:
5.2. 如何调用validatorAction
验证规则的validator元素定义了validatorAction,而field元素则通过depends属性引用了这些validatorAction。从上面代码样例中的验证主程序可以知道validator.validate()方法是针对某个form元素的,它将对这个form元素的各个field进行验证,对field进行验证也就是调用field元素的depends属性引用的各个validator元素定义的验证方法。
validator元素使用classname、method和methodParams三个属性定义了一个验证方法,比如下面的xml片断就定义了一个验证整数的验证方法validateInt,这个方法带有两个参数,类型依次是java.lang.Object,org.apache.commons.validator.Field。验证方法validateInt将在org.i505.validator.MyTypeValidator代码中实现。
|
讲了这么多,现在的问题是validator.validate()方法是如何调用各个验证方法(比如validateInt)的?
我们用一个顺序图和一段代码剖析这个问题。
上图是个简要的顺序图,这个顺序图的解释图下:
1. 向validator对象增加资源(向资源map增加项)
2. 实际验证
对form定义的每个field,调用如下步骤:
#begin
3. 验证一个field
对field的每个validatoraction,执行如下步骤:
#begin
4. 验证一个validatoraction
5. 合并验证结果
#end
#end
下面代码详细解释了上面的第四步:验证一个validatoraction。
|
这段代码首先增加了两个资源:目前正在验证的field和validatoraction,接着实例化验证方法所在类的一个对象,接着按照资源map的键/值和验证方法的参数类列表构造验证方法的参数列表,最后调用验证方法所在类的一个对象的验证方法。
6. 遗留问题
我们说commons-validator是个通用的验证系统,它确实是个不错的东西,但是要想在实际系统中使用它还需要一定的工作,特别是想利用它的客户端验证时尤为如此。所幸的是struts项目为我们使用这些这个验证系统作了很经典的示范,本人认为有必要把struts项目的这些工作移到commons-validator项目中来,这样它的可用性将大大提高。
7. 总结
作为一个验证的通用框架,有些功能不是立即可用的,它需要开发者再次包装。Struts就重新包装了commons-validator的客户端验证机制,使得这种机制在开发struts程序来说是立即可用的。有了这些包装,剩下的任务就是开发validatoraction来满足不同的验证要求了。另外struts还提供了验证和某个正则表达式匹配的输入,它使用了commons-validator的perl5正则表达式匹配机制。
在开发web信息系统时,除了验证输入外,我们还需要注意数据的输出。Web的界面是html代码,而且这个代码是由浏览器来解释的,如果我们的内部数据包括了html代码的保留字,轻一点危害是破坏浏览器对html的解释,搞坏了我们的最后界面;重一点的是引入安全隐患,瘫痪信息系统。下面这段代码可用于过滤html保留字,学着URLEncoding的样,我把它称为HTMLEncoding:
|
http://www.dingl.com/view.shtml?xh=243
通用验证系统commons-validator相关推荐
- 通用网络验证系统,承载能力强,支持高并发、高承载、多线路
这个网络验证系统基于Php+MySql数据库架构的网络验证系统,安全稳定.性能强悍. 承载能力强,支持高并发.高承载.多线路,支持服务器集群架设,高性能设计,速度非常快,效率非常高. 客户端支持VC. ...
- 品达通用权限系统(Day 5~Day 6)
10. pd-tools-jwt pd-tools-jwt模块的定位是对于jwt令牌相关操作进行封装,为认证.鉴权提供支撑. 提供的功能:生成jwt token.解析jwt token 10.1 认证 ...
- 通用日志系统开发【转】
1.前言 中大型软件项目中,日志系统是不可或缺的组成部分.尤其随着软件规模越来越大,内部结构越来越复杂,日志调试成为一种重要的调试方法.本文介绍了一个通用,高效,简洁的日志系统的设计思路. 文章分两部 ...
- Study Struts Commons Validator
不知怎么的,这两天变得有些迷茫了,项目接近尾声了,但自己却不知道自己要干什么了,或许是这个时候状态不好,慢慢的就能够恢复了,不过还好的是,发现这个时候写写程序,倒还能够很好的过去,头脑似乎陷入了某种僵 ...
- 品达通用权限系统(Day 1~Day 2)
1. 项目概述 1.1 项目介绍 对于企业中的项目绝大多数都需要进行用户权限管理.认证.鉴权.加密.解密.XSS防跨站攻击等.这些功能整体实现思路基本一致,但是大部分项目都需要实现一次,这无形中就形成 ...
- 端到端说话人验证系统中长度归一化的分析
Analysis of Length Normalization in End-to-End Speaker Verification System 端到端说话人验证系统中长度归一化的分析 摘要 经典 ...
- 2022-5-1-jjk网络验证系统开源--服务端
2022-5-1-jjk网络验证系统开源 服务端代码 服务端相关代码 http协议 通讯 .版本 2.程序集 通讯.子程序 初始化服务端, 逻辑型全_通信句柄 = 全_Http服务端.创建 (假) . ...
- php 域名验证系统_PHP授权验证系统(域名+IP双重验证一键更新授权系统)
亲,想把你自己的网站程序做个授权吗? 这个程序价值两万多,是目前最新的网站授权平台! 最新授权验证平台2.1,增加管理员登录安全码. 里面包含授权升级DOME仅作参考! 增加服务器IP+域名双重授权模 ...
- PD003-NET通用后台系统
PD003-NET通用后台系统 开发语言.Net 成品成品 前端技术jquery 数据库sql server .net 通用后台框架 详细信息 基于EF+MVC+Bootstrap构建通用后台管理系统 ...
最新文章
- [Leetcode] Max Area of Island 最大岛屿面积
- JQuery中的特殊选择器--this
- c语言readline库6,readline-6.3 之arm平台交叉编译
- C和指针之高级指针话题通过函数指针实现在链表中找到特定的值
- JavaScript之常用方法讲解
- visual studio 设计器不显示_设计模式 | Iterator设计模式
- 智能家居制作之WiFi遥控家中设备
- 华为上半年手机销量_2020年上半年华为发布的新手机盘点
- Shiro 完整教程及样例demo
- MyBatis缓存机制详解
- 计算机设备替换法,同义词替换表的挖掘方法及装置、电子设备、计算机可读介质与流程...
- ps抠图技巧,抠头发
- Kaggle下载criteo数据集
- 使用阿里云服务器的经历~
- AVFounction学习笔记之--音视频播放.md
- MySQL~MySQL数据管理
- Outlook设置Gmail邮箱步骤
- 新年,你拥有一个新灵魂了吗?
- 2022年中国智慧园区市场洞察报告 附下载
- 解读云原生的2021:抢占技术C位,迎来落地大爆发