Struts原理與實(shí)踐(6) - -
本文我們來(lái)討論一下Struts中的輸入校驗(yàn)問(wèn)題。我們知道,信息系統(tǒng)有垃圾進(jìn)垃圾出的特點(diǎn),為了避免垃圾數(shù)據(jù)的輸入,對(duì)輸入進(jìn)行校驗(yàn)是任何信息系統(tǒng)都要面對(duì)的問(wèn)題。在傳統(tǒng)的編程實(shí)踐中,我們往往在需要進(jìn)行校驗(yàn)的地方分別對(duì)它們進(jìn)行校驗(yàn),而實(shí)際上需要校驗(yàn)的東西大多都很類似,如必需的字段、日期、范圍等等。因此,應(yīng)用程序中往往到處充斥著這樣一些顯得冗余的代碼。而與此形成鮮明對(duì)照的是Struts采用Validator框架(Validator框架現(xiàn)在是Jakarta Commons項(xiàng)目的一部分)來(lái)解決校驗(yàn)問(wèn)題,它將校驗(yàn)規(guī)則代碼集中到外部的且對(duì)具體的應(yīng)用程序中立的.xml文件中,這樣,就將那些到處出現(xiàn)的校驗(yàn)邏輯從應(yīng)用程序中分離出來(lái),任何一個(gè)Struts應(yīng)用都可以使用這個(gè)文件,同時(shí)還為校驗(yàn)規(guī)則的擴(kuò)展提供了便利。更難能可貴的是由于Validator框架將校驗(yàn)中要用到的一些消息等信息與資源綁定有機(jī)結(jié)合在一起,使得校驗(yàn)部分的國(guó)際化編程變得十分的便捷和自然。
Validator框架大致有如下幾個(gè)主要組件:
Validators:是Validator框架調(diào)用的一個(gè)Java類,它處理那些基本的通用的校驗(yàn),包括required、mask(匹配正則表達(dá)式)、最小長(zhǎng)度、最大長(zhǎng)度、范圍、日期等
.xml配置文件:主要包括兩個(gè)配置文件,一個(gè)是validator-rules.xml,另一個(gè)是validation.xml。前者的內(nèi)容主要包含一些校驗(yàn)規(guī)則,后者則包含需要校驗(yàn)的一些form及其組件的集合。
資源綁定:提供(本地化)標(biāo)簽和消息,缺省地共享struts的資源綁定。即校驗(yàn)所用到的一些標(biāo)簽與消息都寫在ApplicationResources.properity文件中。
Jsp tag:為給定的form或者action path生成JavaScript validations。
ValidatorForm:它是ActionForm的一個(gè)子類。
為了對(duì)Validator框架有一個(gè)比較直觀的認(rèn)識(shí),我們還是以前面的登陸例子的輸入來(lái)示范一下Validator框架的使用過(guò)程:
首先,找一個(gè)validator-rules.xml文件放在mystruts\WEB-INF目錄下,下面是該文件中涉及到的required驗(yàn)證部分代碼的清單:
<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>
① 節(jié)的代碼是引用一個(gè)服務(wù)器邊的驗(yàn)證器,其對(duì)應(yīng)的代碼清單如下:
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; }}
② 節(jié)是驗(yàn)證失敗后的出錯(cuò)信息,要將對(duì)應(yīng)這些鍵值的信息寫入到ApplicationResources.properity文件中,常見(jiàn)的錯(cuò)誤信息如下:
# Standard error messages for validator framework checkserrors.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.
③ 節(jié)的代碼用于客戶邊的JavaScript驗(yàn)證
其次,在validation.xml文件中配置要驗(yàn)證的form極其相應(yīng)的字段,下面是該文件中的代碼:
<?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>
這里要注意的是:該文中的和中的鍵值都是取自資源綁定中的。前面還講到了出錯(cuò)信息也是寫入ApplicationResources.properity文件中,因此,這就為國(guó)際化提供了一個(gè)很好的基礎(chǔ)。
再次,為了使服務(wù)器邊的驗(yàn)證能夠進(jìn)行,將用到的formBean從ActionForm的子類改為ValidatorForm的子類,即:
將public class UserInfoForm extends ActionForm改為:public class UserInfoForm extends ValidatorForm
到此,進(jìn)行服務(wù)器邊的驗(yàn)證工作已經(jīng)一切準(zhǔn)備得差不多了,此時(shí),只要完成最后步驟就可以實(shí)驗(yàn)服務(wù)器邊的驗(yàn)證了。但大多數(shù)情況下,人們總希望把這些基本的簡(jiǎn)單驗(yàn)證放在客戶邊進(jìn)行。
為了能進(jìn)行客戶邊的驗(yàn)證,我們還要對(duì)logon.jsp文件做適當(dāng)?shù)男薷摹?div style="height:15px;">
<html:form action="/logonAction.do" focus="username" onsubmit="return validateUserInfoForm(this)">
<html:javascript dynamicJavascript="true" staticJavascript="true" formName="userInfoForm"/>