首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

通用验证系统(5)内部剖析

通用验证系统(5)内部剖析

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 代码中实现。
1
2
3
4
5
<validator name="int"   
    classname="org.i505.validator.MyTypeValidator"
    method="validateInt"      
    methodParams="java.lang.Object,org.apache.commons.validator.Field"
    msg="errors.int"/>




讲了这么多,现在的问题是 validator.validate()方法是如何调用各个验证方法(比如 validateInt)的?
我们用一个顺序图和一段代码剖析这个问题。
顺序图上图是个简要的顺序图,这个顺序图的解释图下:
1. 向 validator 对象增加资源(向资源 map 增加项)
2. 实际验证
对 form 定义的每个 field,调用如下步骤:
#begin
3. 验证一个 field
对 field 的每个 validatoraction,执行如下步骤:
#begin
4. 验证一个 validatoraction
5. 合并验证结果
#end
#end
下面代码详细解释了上面的第四步:验证一个 validatoraction。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Add these two Objects to the resources since they reference  
// the current validator action and field   
hResources.put(VALIDATOR_ACTION_KEY, va);   
hResources.put(FIELD_KEY, field);      
Class c = getClassLoader().loadClass(va.getClassname());   
List lParams = va.getMethodParamsList();      
int size = lParams.size();      
int beanIndexPos = -1;      
int fieldIndexPos = -1;   
Class[] paramClass = new Class[size];         
Object[] paramValue = new Object[size];      
for (int x = 0; x < size; x++) {            
    String paramKey = (String) lParams.get(x);
    if (BEAN_KEY.equals(paramKey)) {         
        beanIndexPos = x;         
    }      
    if (FIELD_KEY.equals(paramKey)) {     
        fieldIndexPos = x;               
    }
    // There were problems calling getClass on paramValue[]
    paramClass[x] = getClassLoader().loadClass(paramKey);
    paramValue[x] = hResources.get(paramKey);      
}      
Method m = c.getMethod(va.getMethod(), paramClass);     
// If the method is static we don't need an instance of the class
// to call the method.  If it isn't, we do.        
if (!Modifier.isStatic(m.getModifiers())) {      
    try {              
        if (va.getClassnameInstance() == null) {   
            va.setClassnameInstance(c.newInstance());
        }
    }
    catch (Exception ex) {           
        log.error(                 
           "Couldn't load instance "         
            + "of class "                 
            + va.getClassname()         
            + ".  "                 
            + ex.getMessage());     
        }
    }
    Object result = null;           
    if (field.isIndexed()) {        
        Object oIndexed =           
            PropertyUtils.getProperty(   
            hResources.get(BEAN_KEY),     
            field.getIndexedListProperty());   
            Object indexedList[] = new Object[0];
            if (oIndexed instanceof Collection) {  
                indexedList = ((Collection) oIndexed).toArray();   
            }
            else if (oIndexed.getClass().isArray()) {  
                indexedList = (Object[]) oIndexed;      
            }   
            // Set current iteration object to the parameter array
            paramValue[beanIndexPos] = indexedList[pos];   
            // Set field clone with the key modified to represent     
            // the current field           
            Field indexedField = (Field) field.clone();         
            indexedField.setKey(               
            ValidatorUtil.replace(         
                indexedField.getKey(),      
                Field.TOKEN_INDEXED,        
               "[" + pos + "]"));  
                paramValue[fieldIndexPos] = indexedField;     
                result = m.invoke(va.getClassnameInstance(), paramValue);
                results.add(field, va.getName(), isValid(result), result);
                if (!isValid(result)) {           
                    return false;              
                }
            }
            else {         
                result = m.invoke(va.getClassnameInstance(), paramValue);
                results.add(field, va.getName(), isValid(result), result);
                if (!isValid(result)) {            
                    return false;               
                }
            }




这段代码首先增加了两个资源:目前正在验证的 field 和 validatoraction,接着实例化验证方法所在类的一个对象,接着按照资源 map                的键 / 值和验证方法的参数类列表构造验证方法的参数列表,最后调用验证方法所在类的一个对象的验证方法。
返回列表