1. 程式人生 > >Struts原理與實踐(6)

Struts原理與實踐(6)

本文我們來討論一下Struts中的輸入校驗問題。我們知道,資訊系統有垃圾進垃圾出的特點,為了避免垃圾資料的輸入,對輸入進行校驗是任何資訊系統都要面對的問題。在傳統的程式設計實踐中,我們往往在需要進行校驗的地方分別對它們進行校驗,而實際上需要校驗的東西大多都很類似,如必需的欄位、日期、範圍等等。因此,應用程式中往往到處充斥著這樣一些顯得冗餘的程式碼。而與此形成鮮明對照的是Struts採用Validator框架(Validator框架現在是Jakarta Commons專案的一部分)來解決校驗問題,它將校驗規則程式碼集中到外部的且對具體的應用程式中立的.xml檔案中,這樣,就將那些到處出現的校驗邏輯從應用程式中分離出來,任何一個Struts應用都可以使用這個檔案,同時還為校驗規則的擴充套件提供了便利。更難能可貴的是由於Validator框架將校驗中要用到的一些訊息等資訊與資源繫結有機結合在一起,使得校驗部分的國際化程式設計變得十分的便捷和自然。

    Validator框架大致有如下幾個主要元件:

    Validators:是Validator框架呼叫的一個Java類,它處理那些基本的通用的校驗,包括required、mask(匹配正則表示式)、最小長度、最大長度、範圍、日期等

    .xml配置檔案:主要包括兩個配置檔案,一個是validator-rules.xml,另一個是validation.xml。前者的內容主要包含一些校驗規則,後者則包含需要校驗的一些form及其元件的集合。

    資源繫結:提供(本地化)標籤和訊息,預設地共享struts的資源繫結。即校驗所用到的一些標籤與訊息都寫在ApplicationResources.properity檔案中。

    Jsp tag:為給定的form或者action path生成JavaScript validations。

    ValidatorForm:它是ActionForm的一個子類。

    為了對Validator框架有一個比較直觀的認識,我們還是以前面的登陸例子的輸入來示範一下Validator框架的使用過程:

    首先,找一個validator-rules.xml檔案放在mystruts/WEB-INF目錄下,下面是該檔案中涉及到的required驗證部分程式碼的清單:

<validator name="required"
<!--①-->
            classname="org.apache.struts.validator.FieldChecks"
               method="validateRequired"
         methodParams="java.lang.Object,
                       org.apache.commons.validator.ValidatorAction,
                       org.apache.commons.validator.Field,
                       org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest"
<!--②-->
                  msg="errors.required">
<!--③-->
         <javascript><![CDATA[
            function validateRequired(form) {
                var isValid = true;
                var focusField = null;
                var i = 0;
                var fields = new Array();
                oRequired = new required();
                for (x in oRequired) {
                	var field = form[oRequired[x][0]];
                	
                    if (field.type == 'text' ||
                        field.type == 'textarea' ||
                        field.type == 'file' ||
                        field.type == 'select-one' ||
                        field.type == 'radio' ||
                        field.type == 'password') {
                        
                        var value = '';
				// get field's value
				if (field.type == "select-one") {
				var si = field.selectedIndex;
				if (si >= 0) {
				value = field.options[si].value;
							}
						} else {
							value = field.value;
						}
                        
                        if (trim(value).length == 0) {
                        
	                        if (i == 0) {
	                            focusField = field;
	                        }
	                        fields[i++] = oRequired[x][1];
	                        isValid = false;
                        }
                    }
                }
                if (fields.length > 0) {
                   focusField.focus();
                   alert(fields.join('/n'));
                }
                return isValid;
            }
            
            // Trim whitespace from left and right sides of s.
            function trim(s) {
                return s.replace( /^/s*/, "" ).replace( //s*$/, "" );
            }
            
            ]]>
         </javascript>

</validator>

    ① 節的程式碼是引用一個伺服器邊的驗證器,其對應的程式碼清單如下:

public static boolean validateRequired(Object bean,
                                           ValidatorAction va, Field field,
                                           ActionErrors errors,
                                           HttpServletRequest request) {

        String value = null;
        if (isString(bean)) {
            value = (String) bean;
        } else {
            value = ValidatorUtil.getValueAsString(bean, field.getProperty());
        }
        
        if (GenericValidator.isBlankOrNull(value)) {
            errors.add(field.getKey(), Resources.getActionError(request, va, field));
            return false;
        } else {
            return true;
        }
}

    ② 節是驗證失敗後的出錯資訊,要將對應這些鍵值的資訊寫入到ApplicationResources.properity檔案中,常見的錯誤資訊如下:

# Standard error messages for validator framework checks
errors.required={0} is required.
errors.minlength={0} can not be less than {1} characters.
errors.maxlength={0} can not be greater than {1} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is an invalid credit card number.
errors.email={0} is an invalid e-mail address.

    ③ 節的程式碼用於客戶邊的JavaScript驗證

其次,在validation.xml檔案中配置要驗證的form極其相應的欄位,下面是該檔案中的程式碼:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation
//DTD Commons Validator Rules Configuration 1.0//EN" 
"http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">
<form-validation>
<formset>
<form name="userInfoForm">
<field property="username"
depends="required,mask,minlength,maxlength">
<arg0 key="logon.jsp.prompt.username" resource="true"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<var>
<var-name>mask</var-name>
<var-value>^/w</var-value>
</var>
<var>
<var-name>minlength</var-name>
<var-value>2</var-value>
</var>
<var>
<var-name>maxlength</var-name>
<var-value>16</var-value>
</var>
</field>
<field property="password"
depends="required,minlength,maxlength">
<arg0 key="logon.jsp.prompt.password" resource="true"/>
<arg1 name="minlength" key="${var:minlength}" resource="false"/>
<arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
<var>
<var-name>minlength</var-name>
<var-value>2</var-value>
</var>
<var>
<var-name>maxlength</var-name>
<var-value>16</var-value>
</var>
</field>
</form>
</formset>
</form-validation>

    這裡要注意的是:該文中的和中的鍵值都是取自資源繫結中的。前面還講到了出錯資訊也是寫入ApplicationResources.properity檔案中,因此,這就為國際化提供了一個很好的基礎。

    再次,為了使伺服器邊的驗證能夠進行,將用到的formBean從ActionForm的子類改為ValidatorForm的子類,即:
    將public class UserInfoForm extends ActionForm改為:public class UserInfoForm extends ValidatorForm

    到此,進行伺服器邊的驗證工作已經一切準備得差不多了,此時,只要完成最後步驟就可以實驗伺服器邊的驗證了。但大多數情況下,人們總希望把這些基本的簡單驗證放在客戶邊進行。

    為了能進行客戶邊的驗證,我們還要對logon.jsp檔案做適當的修改。

    將

<html:form action="/logonAction.do" focus="username">
改為
    
<html:form action="/logonAction.do" focus="username" onsubmit="return validateUserInfoForm(this)">

    在標籤後加上:
    

<html:javascript dynamicJavascript="true" staticJavascript="true" formName="userInfoForm"/>

    最後,對struts的配置檔案struts-config.xml作適當的修改:
    1、將

<action input="/logon.jsp" name="userInfoForm"
 path="/logonAction" scope="session" type="action.LogonAction" validate="false" >
改為
<action input="/logon.jsp" name="userInfoForm" 
path="/logonAction" scope="session" type="action.LogonAction" validate="true" >
其作用是要求進行校驗

    2、將下列程式碼放在struts-config.xml檔案中的標籤前。其作用是將用於校驗的各個元件結合在一起。

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames"
	value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" />
</plug-in>

    到此為止,我們的一切工作準備就緒,您可以享受自己的勞動成果了,試著輸入各種組合的使用者名稱和口令,看看它們的驗證效果。仔細體會你會發現,伺服器邊的驗證要更全面一些,比如對password的字元長度的驗證。