配置 Struts Validation 框架
?????? 相信正在閱讀本文的讀者都是對 struts 有一定經(jīng)驗(yàn)的,對于 struts 到哪去下載、如何安裝配置就不必筆者多言。此處僅僅只討論 struts validation 框架的安裝和配置。通常,我們有 2 種方法來進(jìn)行這個(gè)過程。
-????????? 方法一:
從 struts 自帶的 webapps 目錄下解壓 struts-balnk.war 到項(xiàng)目的 web 工程目錄。這是最簡單創(chuàng)建 struts 工程的方式,在這個(gè)工程中就已經(jīng)包含了一個(gè) struts 應(yīng)用的所有需要的開發(fā)包和這些包的基本配置,自然也包含了其中的 validation 框架。它非常適合在項(xiàng)目的初創(chuàng)階段,我們所需做的就是在這個(gè)空白工程中填點(diǎn)什么就可以了。
-????????? 方法二:
對于已經(jīng)存在的 struts 工程,如何添加 valiadation 框架支持所需的步驟也非常簡單。
1.?????? 首先在 struts-config.xml 中添加以下內(nèi)容
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
??? <set-property property="pathnames"
??????? value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
?</plug-in>
2.?????? 然后在 web-inf 目錄中創(chuàng)建 2 個(gè)文件 validator-rules.xml , validation.xml 。(這 2 個(gè)文件也可從 struts-balnk.war 中獲?。?/span>
3.?????? 復(fù)制 validation 框架所需要的類包到 web-inf/lib 下,這些類包是: common-validator.jar 。
這樣,我們就可以使用 struts 的 validation 框架了。
使用 validation 框架
????? 問題
?????? 這是一個(gè)簡單的用戶管理程序,使用者可以對用戶信息進(jìn)行相應(yīng)的 CRUD 操作(增查改刪)。其中用戶信息包含用戶名稱、用戶地址、用戶描述、用戶密碼。對于以上的各種操作,約束如下:
-????????? 增加和修改:用戶名稱、用戶地址、用戶密碼、用戶密碼確認(rèn)為必填項(xiàng),同時(shí)密碼和確認(rèn)密碼 2 個(gè)域的值必須一致。
-????????? 刪除和查詢:用戶名稱為必填項(xiàng)。
解決和使用步驟
1.?????? 創(chuàng)建 struts 項(xiàng)目的基本環(huán)境。
2.?????? 創(chuàng)建相應(yīng)的頁面,確定頁面流程( page flow )。
3.?????? 創(chuàng)建相應(yīng)的 formbean :
2??????? strut1.1 版本解決辦法:
為了簡單起見使用 DynaActionForm 。又由于使用了 validation 框架,此處使用 DynaValidatorForm 。 struts-config.xm 的內(nèi)容:
<form-bean name="editForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="id" type="java.lang.Integer"/>
<form-property name="name" type="java.lang.String"/>
???? <form-property name="pwd1" type="java.lang.String"/>
???? <form-property name="pwd2" type="java.lang.String"/>
<form-property name="address" type="java.lang.String"/>
<form-property name="desc" type="java.lang.String"/>
</form-bean>
然后,修改 web-inf 目錄下的 validation.xml 文件內(nèi)容,其中 form 的名字和各域的名字必須和 struts-config.xml 中一致:
<form name="/editForm ">
???? <field property="name" depends="required">
????????? <arg0 key="editForm.name"/>
???? </field>
???? <field property="pwd1" depends="required,mask">
??
??
?
????<arg0 key="editForm.password"/>
????????? <var>
??????????????? <var-name>mask</var-name>
??????????????? <var-value>^[0-9a-zA-Z]*$</var-value>
????????? </var>
???? </field>
???? <field property="pwd2" depends="required,mask">
????????? <arg0 key="editForm.password"/>
????????? <var>
??????????????? <var-name>mask</var-name>
??????????????? <var-value>^[0-9a-zA-Z]*$</var-value>
????????? </var>
???? </field>
<field property="address" depends="required ">
????????? <arg0 key="editForm.address"/>
???
?</field>
</form>
4.?????? 創(chuàng)建相應(yīng)的 Action ,同時(shí) Action 的 validate 屬性置為 true ,以啟用 validation 框架。
5.?????? 書寫 ApplicationResources.properties ,添加錯(cuò)誤信息。
2??????? struts1.1
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.
editForm.name= name.
editForm.password= password.
editForm.address= address
6.?????? 在相應(yīng)的 jsp 中添加 <html:errors property="age"/>
從整個(gè)使用過程來看,就驗(yàn)證部分而言,使用 struts1.1 的開發(fā)效率大大的得到了提高,而且通過 validator-rules.xml 使驗(yàn)證方法能被不同的 formbean 復(fù)用,而且可維護(hù)性也大大的得到提高。通過 mask ,使得單個(gè)頁面域的驗(yàn)證非常靈活。
但是細(xì)心的讀者可能也發(fā)現(xiàn)了這個(gè)驗(yàn)證文件僅僅指明 2 個(gè) password 域是必填的,但并沒有滿足他們必須是相等的這種情形的判斷,對于這一點(diǎn),我們可使用自定義的 validator 并將它添加到 validator-rules.xml 文件中來完成。
創(chuàng)建自定義的 validator
?????? 對于 validator 的創(chuàng)建,可以歸結(jié)為 3 步:
1.?????? 創(chuàng)建 validator 類, validator 必須包含一個(gè)以 validate 開始的方法,并且它的函數(shù)簽名必須如下:
validateXXX(java.lang.Object,
org.apache.commons.validator.ValidatorAction,
org.apache.commons.validator.Field,? org.apache.struts.action.ActionErrors,
javax.servlet.http.HttpServletRequest,? javax.servlet.ServletContext)
在本例中,自定義的 Validator 如下(摘至 Struts 提供的例子,用來提供 2 個(gè)域的相等性檢查):
????????????? public class CustomValidator {
public CustomValidator() {
super();
}
public static boolean validateTwoFields(? Object bean,
ValidatorAction va, Field field, ActionErrors errors, HttpServletRequest request) {
String value = ValidatorUtil.getValueAsString(bean, field.getProperty());
String sProperty2 = field.getVarValue("secondProperty");
String value2 = ValidatorUtil.getValueAsString(bean, sProperty2);
if (!GenericValidator.isBlankOrNull(value)) {
try {
if (!value.equals(value2)) {
errors.add( field.getKey(), Resources.getActionError(request, va, field));
return false;
}
} catch (Exception e) {
errors.add( field.getKey(), Resources.getActionError(request, va, field));
return false;
}
}
return true;
}
}
2.?????? 添加到 validator-rules.xml 文件中:
<validator name="twofields" classname="examples.validator.CustomValidator"
???? method="validateTwoFields" 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.twofields" />
??????????????????
在對應(yīng)的屬性文件中添加對應(yīng)的消息(
errors.twofiled
)。
3.?????? 在 validation.xml 中使用:
<field property="pwd1" depends="required,twofields">
???????? <arg0 key="editForm.password" />
?????????? <arg1 name="twofields" key=" editForm.password2" />
?????????? <var>
??????????????????? <var-name>secondProperty</var-name>
??????????????????? <var-value>pwd2</var-value>
?????????? </var>
</field>
????????
通過自定義
validator
,
validation
框架的可擴(kuò)展性大大的得到提高。而且也使得不同的驗(yàn)證方法能夠很好的得到復(fù)用
javascript 支持
?????? 在 web 應(yīng)用中,使用 javascript 的機(jī)會非常多。雖然不少書上提及客戶有可能從瀏覽器關(guān)閉 js 的執(zhí)行,但是要想完全的不使用它,目前看來好像還不行。比如一些復(fù)雜的 UI 是必須通過 js 來實(shí)現(xiàn)的(如下拉式菜單等等)。那么 validation 框架支不支持客戶端的 js 驗(yàn)證呢?
答案是:當(dāng)然。具體做法是:
-????????? 在頁面 html:form 標(biāo)簽內(nèi)部添加 onsubmit="return validateEditForm(this);" (具體的語法: validate+ 在 validation.xml 文件中定義的 form 的名字);如:
<html:form action="<%=action%>" method="post" onsubmit="return validateEditForm(this);">
-?????????
在
html:form
內(nèi)部塊中添加:
<html:javascript formName="editForm"/>
?????? 如此 2 步即可。雖然, validation 框架非常簡單易用,但是還是有需要注意的地方。
使用注意
1.?????? 使用 validation 框架后, form 必須從 ValidatorForm 中派生,同時(shí)必須在你的 validate 方法中先調(diào)用基類的 validate 方法。對于使用 Dyna 開頭的方法來創(chuàng)建 formbean 的讀者,你也必須改為以 dyna 開頭含有 validator 的 form 。
2.?????? 注意 DynaValidatorForm ( ValidatorForm )和 DynaValidatorActionForm ( ValidatorActionForm )的區(qū)別。剛開始時(shí)從幫助中沒看明白這 2 者的區(qū)別,后來從網(wǎng)上一篇文章中得到了用法的區(qū)別。前者主要的視角是 formbean ,而后者的視角是 action 。
當(dāng) formbean 被不同的 action 使用時(shí),對于不同的 action 而言,使用的 formbean 的屬性集合有大有小。此時(shí)如果仍然以 formbean 為主體,會造成其他 action 的不正常使用。因此, struts 中提出了 DynaValidatorActionForm ( ValidatorActionForm )。此時(shí)在 validation.xml 中的 form 標(biāo)簽的 name 屬性改為 action 的 path 屬性,又由于 action 中有 attribute 和 name 屬性, validation 框架就可根據(jù)這個(gè) action 得到對應(yīng)的 formbean 。例子:
<formset>
? <form name="/createAddress">
??? <field property="city"
????????? depends="required">
????? <arg0 key="prompt.city"/>
??? </field>
? </form>
? <form name="/editAddress">
??? <field property="state"
????????? depends="required">
????? <arg0 key="prompt.state"/>
??? </field>
? </form>
</formset>
3.?????? 與 DispatchAction 的配合。 Struts1.1 的 DispatchAction 使得相關(guān)的 Action 的關(guān)系緊密,大大減少了應(yīng)用中 Action 的個(gè)數(shù),但是隨之而來也帶來了使用 Validation 框架的不便,不能不說是一個(gè)遺憾。讀者也許認(rèn)為這種情況可以使用第 2 條的解決方案來解決,即采用 DyanValidatorActionForm ,然后在 Validation.xml 文件中 form 的名稱使用不同的 Actiond 的 path ,即在 validation.xml 中使用: <form name="/user.do?method=doAdd"> 、 ??? <form name="/user.do?method=doLoad"> 。然而,在目前的版本中 Validation 框架并不支持這種辨認(rèn)。一種繞過這個(gè)情況的方法是,針對同一個(gè) Action 實(shí)現(xiàn)類在 Struts-config.xml 文件中定義多個(gè) Action 的 path ,在不需要進(jìn)行驗(yàn)證的地方將 Action 的 validate 屬性置為 false 。即:
struts-config.xml :
<action attribute="editForm" path="/user" name="editForm" input="/editUser.jsp"
parameter="method" scope="request" type="foxgem.struts.UserDispatchAction"
???? validate="true">
?????????????? <forward name="load" path="/editUser.jsp"/>
?????????????? <forward name="action" path="/userquery.do?pageId=1"/>
</action>
???????
<action attribute="editForm" path="/loaduser" name="editForm" input="/editUser.jsp"
??????? ? parameter="method" scope="request" type="foxgem.struts.UserDispatchAction"
??????? ? validate="false">
?????????????? <forward name="load" path="/editUser.jsp"/>
?????????????? <forward name="action" path="/userquery.do?pageId=1"/>
</action>
然后在
validation.xml
文件中使用
2
的方法。
結(jié)束語
?????? 總的說來, validation 框架大大的提高了頁面驗(yàn)證的開發(fā)效率,更吸引人的是這些驗(yàn)證方法可通過自定義的 validator 來得到復(fù)用。使得這些驗(yàn)證代碼更加集中,可維護(hù)性得到加強(qiáng)。當(dāng)然隨著項(xiàng)目的進(jìn)行, validation.xml 和 validator-rules.xml 會隨之增長,這部分的維護(hù)工作加重了。
?????? 同時(shí),由于不能非常好的和 DispatchAction 一起協(xié)作,也使得大量使用 DispatchAction 的項(xiàng)目不能非常好的使用它。建議大量使用 DispatchAction 和頁面驗(yàn)證非常復(fù)雜多變的項(xiàng)目可以暫時(shí)按原來的方法來驗(yàn)證,不使用 validation 框架。
?????? 至于 validation 框架的其他詳細(xì)信息,請參見 struts 的文檔,在此不再贅述。
關(guān)于作者
胡鍵,西安交通大學(xué)工學(xué)碩士,熱衷于
j2ee/.net
技術(shù),是
OpenSource
的忠實(shí)擁護(hù)者。目前與友人創(chuàng)建西安爍程軟件有限公司。公司主要致力于
java web
應(yīng)用的開發(fā),已有多個(gè)項(xiàng)目在能源、電力和交通行業(yè)得到應(yīng)用??梢酝ㄟ^
james.hu@chinacodeline.com
與他取得聯(lián)系。