一、背景:
数据校验一直是应用开发中重要的必不可少的功能,Flex框架本身也提供了大量的易于使用的数据验证组件,如StringValidator,NumberValidator等,但使用时需要如下定义:
<mx:StringValidator id="srvcod_stringValidator" source="{srvcod}" requiredFieldError="请输入服务代码" property="text"/>
如果同一个实体对象应用在不同的输入页面中也需要重复定义,所以参考了hibernate validation的思路将校验规则用元数据的方式定义在实体对象或者页面数据对象中,这样就避免了可能出现重复定义的情况,同时个人感觉也比较容易维护。
二、代码:
代码比较简单,两个工具类:ReflectionUtil和ValidationUtil
ReflectionUtil用于解析实体对象中定义的元数据:
package util
{
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;
import mx.collections.ArrayCollection;
import mx.effects.AddItemAction;
/**
* The ReflectionUtil class privodes an mechanism to get meta data of a object or class
*/
public class ReflectionUtil
{
private static var metadataMap:Object = new Object();
public function ReflectionUtil()
{
}
public static function getInstanceByName(className:String):Object{
var c:Class = Class(getDefinitionByName(className));
return new c();
}
public static function getClassName(instance:Object):String{
return getQualifiedClassName(instance);
}
public static function getSuperClassName(instance:Object):String{
return getQualifiedSuperclassName(instance);
}
public static function getClass(o:Object):Class{
var c:Class = Class(getDefinitionByName(getQualifiedClassName(o)));
return c;
}
public static function loadMetadata(instance:Object):Object{
var clazz:Class = ReflectionUtil.getClass(instance);
if (!metadataMap[clazz]){
trace("load meta data of " + clazz);
var xml:XML = describeType(new clazz());
metadataMap[clazz] = new Object();
metadataMap[clazz].fields = new ArrayCollection();
var variables:XMLList = xml.variable;
for each(var variable:Object in variables){
var fieldName:String = variable.@name.toString();
var fieldType:String = variable.@type.toString();
var field:Object = new Object();
field["name"] = fieldName;
field["type"] = fieldType;
var metadatas:XMLList = variable.metadata;
if (metadatas){
for each(var metadata:Object in metadatas){
var metadataName:String = metadata.@name.toString();
if (metadataName != "__go_to_definition_help"){ //TODO: exclude string.
field[metadataName] = new Object();
field[metadataName].tags = new ArrayCollection();
var args:XMLList = metadata.arg;
for each(var arg:Object in args){
var argName:String = arg.@key.toString();
var argValue:String = arg.@value.toString();
if(argName=="type"){
field[metadataName].type = argValue;
}
else{
field[metadataName].tags.addItem({tagName:argName,tagValue:argValue});
}
}
}
}
}
metadataMap[clazz].fields.addItem(field);
}
}
return metadataMap[clazz];
}
}
}
ValidationUtil用于根据定义实例化Flex中的通用validator并执行校验工作:
package util
{
import mx.collections.ArrayCollection;
import mx.events.ValidationResultEvent;
import mx.validators.Validator;
/**
* The ValidationUtil class helps user to validate the form data in an easy way.
*/
public class ValidationUtil
{
public function ValidationUtil()
{
}
/**
* Validate an object which is with Valid annotations.
*/
public static function validate(instance:Object):ArrayCollection{
var clazz:Class = ReflectionUtil.getClass(instance);
var medadata:Object = ReflectionUtil.loadMetadata(instance);
var validationResults:ArrayCollection = new ArrayCollection();
if (medadata){
for each(var field:Object in medadata.fields){
if (field.Valid){
var validType:String = field.Valid.type;
var validator:Validator = ReflectionUtil.getInstanceByName(validType) as Validator;
if (field.Valid.tags){
for each(var tag:Object in field.Valid.tags){
var tagName:String = tag.tagName;
var tagValue:Object = tag.tagValue;
validator[tagName] = tagValue;
}
}
//valid data
var data:Object = instance[field.name];
var result:ValidationResultEvent = validator.validate(data);
validationResults.addItem(result);
}
}
}
return validationResults;
}
}
}
实体对象:
package util
{
public class UserVo
{
[Valid(type="mx.validators.NumberValidator", required="true",minValue=1000,maxValue=5000)]
public var contactId:int;
[Valid(type="mx.validators.StringValidator", required="true",minLength=5,maxLength=10)]
public var firstName:String;
public var lastName:String;
public var address:String;
}
}
使用比较简单,调用ValidationUtil.validate(obj)即可得到验证结果。