原创作者: reverocean   阅读:2794次   评论:0条   更新时间:2011-06-01    
在struts中的actionform中验证是经常使用的,虽然也可以使用validation来进行验证,但是在没有学习validation的时候就只能使用在actionform中验证啦。

下面是我的一些想法,不知道合不合适,请大家讨论一下:^_^

在现在的应用中有很多需要验证页面输入的内容是不是空、是不是数字、是不是Double、是不是Int、是不是Float、是不是Email格式、是不是电话格式、是不是邮政编码格式等等验证,在编码中不得不对每一个属性进行验证,这些代码都重复的。因此,如果将这些验证的代码放到一个父类中,那么将会减少编写的代码良,同时也能够很好的对验证的格式做出一个调整。比如说如果验证中国的邮政编码的格式改为验证其他国家的邮政编码,只需要修改配置文件中的邮政编码的正则表达式即可,不用修改代码。下面是实现的一些分析:
1. 从Properties文件中读取配置文件的类:
将数字、Email、电话和邮政编码等的格式的正则表达式写在一个properties文件中,便于修改。其regex .properties文件的内容如下:
numberRegex ="\\d"
emailRegex = "\\S+@\\S+\\.\\S+"
postCodeRegex =" \\d\\d\\d\\d\\d"
………………
在程序中使用如下代码进行匹配邮政编码的格式:
protected boolean isValidPostalCode(String str){
        try{
        Pattern pattern = Pattern.compile(
//从properties文件里读入邮政编码格式的正则表达式
PropertyReader.getValueByKey(Constants.POSTAL_CODE));
//进行匹配,返回结果
        return pattern.matcher(str).matches();           
        }catch(Exception e){
            return false;
        }
    }

其他验证均是如此。此外改方法式protected的方法,可以被子类覆盖、调用。
2. 其他一些验证方法:
a) 验证字符串是否为空的函数:
protected boolean isBlankString(String str){
        if(str == null) {
            return true;
        }
        return (str.length() == 0);
    }

b) 验证输入内容式Double类型的函数:
protected boolean isDouble(String str){
       try{
           Double.parseDouble(str);
           return true;
       }catch(Exception e){
           return false;
       }
    }
其他验证Float、Int类型的函数同Double类型的函数一样,没有什么区别。同样他们都是protected的函数,可以被子类覆盖,调用。
3. 覆盖validate()方法:
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
       ActionErrors errors = new ActionErrors();
       ActionErrors tempErrors = null;
       //-----------------------------------------------------
       //Validate required!
  ///验证输入内容必须输入的属性的函数
       //-----------------------------------------------------
       tempErrors = validateRequired();
       if(tempErrors != null){
           errors.add(tempErrors);
       }
       //-----------------------------------------------------
       //Validate postal code!
       //-----------------------------------------------------
       tempErrors = validatePostalCode();
       if(tempErrors != null){
           errors.add(tempErrors);
       }
       //-----------------------------------------------------
       //Validate double!
       //-----------------------------------------------------
       tempErrors = validateDouble();
       if(tempErrors != null){
           errors.add(tempErrors);
       }
       //-----------------------------------------------------
       //Validate phone!
       //-----------------------------------------------------
       tempErrors = validatePhone();
       if(tempErrors != null){
           errors.add(tempErrors);
       }
       //-----------------------------------------------------
       //Validate state!
       //-----------------------------------------------------
       tempErrors = validateState();
       if(tempErrors != null){
           errors.add(tempErrors);
       }
       //-----------------------------------------------------
       //Validate email!
       //-----------------------------------------------------
       tempErrors = validateEmail();
       if(tempErrors != null){
           errors.add(tempErrors);
       }
………………………………
………………………………
………………………………
………………………………
………………………………
………………………………

       //-----------------------------------------------------
       //Validate Others
  //可以实现自己与众不同的验证,返回一个ActionErrors对象。
       //-----------------------------------------------------
       tempErrors = validateOthers(mapping,request);
       if(tempErrors != null){
           errors.add(tempErrors);
       }
       return errors;
    }
在该函数里面依次调用验证不能为空的验证方法,必须式Email格式等等的验证函数,最后一个validateOthers()是protected函数,可以被子类覆盖,在子类中实现上面没有实现的验证,然后在将验证的结果ActionErrors对象返回即可。
4. validateRequired()函数的实现:
/**
     * Validate required!
*验证必须输入的属性
     * @return ActionErrors
     */
    private ActionErrors validateRequired(){
//初始化一个ActionErrors对象
        ActionErrors errors = new ActionErrors();
//读取需要进行必须验证的属性列表
        List properties = getRequiredPropertyList();
        String propertyName = "";
        String propertyValue = "";
        if((properties != null)&&(properties.size()>0)){
//依次对需要验证的属性进行验证
            for(int i = 0;i<properties.size();i++){
//获取属性名的字符串
                propertyName = (String)properties.get(i);
//获取对应属性的输入值
                propertyValue = (String)getTheValue(propertyName);
//验证属性值是否为空
                if(this.isBlankString(propertyValue)){
//在Struts的资源文件中定义出错提示信息
//以“属性名”为“key”将错误信息添加到errors中去。
                    errors.add(propertyName,new ActionMessage("stocktrack.newuser.required",propertyName));
                }
            }
        }
//返回结果
        return errors;
    }
getRequiredPropertyList()是获取必须验证属性列表的函数。该函数的定义如下:
protected List getRequiredPropertyList(){
        return null;
}
可见该函数是一个protected的函数,需要子类覆盖。在子类中需要将要进行必须验证的属性名添加到一个List中去,然后将List返回。下面是一个实现的例子:
public List getRequiredPropertyList() {
        List list = new ArrayList();
        list.add("username");
        list.add("password");
        list.add("email");
        list.add("streetAddress1");
        list.add("streetAddress2");
        list.add("city");
        list.add("state");
        list.add("postalCode");
        list.add("homePhone");
        list.add("workPhone");
        return list;
    }
这里的属性名必须与Form类中的属性名相同。
讨论:这里最初的想法是将getRequiredPropertyList()这一类方法定义成为一个抽象(abstract)方法,这样子类中就必须实现改方法,避免忘记实现。但是在一些Form中也不一定都会要验证所有的内容,但是程序员也必须实现那些方法,而且他们实现也是返回null即可。如果在BaseForm类中实现了就不用做这种无用的事情了。请给予指正!

―――――――――――――――――――――――――――――――――

getTheValue(propertyName)方法是用来通过传进去的属性名取出该属性对应的属性值,下面是改方法的实现:
private Object getTheValue(String property){
        Object object = null;
        Method method = null;
        Class clazz = null;
        String methodName = "";
//如果属性名为空,则返回null
        if(isBlankString(property)){
            return null;
        }
//将属性名的第一个字母大写,然后加上get构成属性对应的get方法//名。
//注意:这里的属性名的第一个字符必须是字母,否则会出错。(请
//讨论)
        methodName = "get" + property.substring(0,1).toUpperCase()
+ property.substring(1,property.length());
//从methodsMap(存放方法的一个Map)里面取方法
        method = (Method) methodsMap.get(methodName);
        if(method == null){
//如果methodsMap中不存在方法名,则通过反射得到方法
//获取该类的Class对象
            clazz = getClass();
            try {
//通过反射获取属性名对应的get方法
                method = clazz.getMethod(methodName, new Class[0]);
            } catch (SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
//这里以方法名为key将获取的方法放到methodsMap中,以便
//下次使用的时候不用使用反射。
            methodsMap.put(methodName,method);
        }
        try {
//运行方法,获取属性值
            object = method.invoke(this,new Object[0]);
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
//将属性值返回
        return object;
    }

5. 继承BaseForm之后需要做的事情:
1)添加属性(必须是String型,属性名的第一个字符必须是字母);
2)将需要验证的属性添加到对应的List方法中,然后返回List;
3)如果有没有实现的验证,请覆validateOthers()方法,该方法和普通的validate方法没有不同之处。

6. 没有实现的内容:
属性是数组的情况没有考虑,如果有属性是数组的情况,请自己实现validateOthers方法。
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

文章信息

  • letle在2005-09-13创建
  • letle在2011-06-01更新
Global site tag (gtag.js) - Google Analytics