配置 Struts Validation 框架
?????? 相信正在閱讀本文的讀者都是對 struts 有一定經驗的,對于 struts 到哪去下載、如何安裝配置就不必筆者多言。此處僅僅只討論 struts validation 框架的安裝和配置。通常,我們有 2 種方法來進行這個過程。
-????????? 方法一:
從 struts 自帶的 webapps 目錄下解壓 struts-balnk.war 到項目的 web 工程目錄。這是最簡單創(chuàng)建 struts 工程的方式,在這個工程中就已經包含了一個 struts 應用的所有需要的開發(fā)包和這些包的基本配置,自然也包含了其中的 validation 框架。它非常適合在項目的初創(chuàng)階段,我們所需做的就是在這個空白工程中填點什么就可以了。
-????????? 方法二:
對于已經存在的 struts 工程,如何添加 valiadation 框架支持所需的步驟也非常簡單。
1.?????? 首先在 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>
2.?????? 然后在 web-inf 目錄中創(chuàng)建 2 個文件 validator-rules.xml , validation.xml 。(這 2 個文件也可從 struts-balnk.war 中獲取)。
3.?????? 復制 validation 框架所需要的類包到 web-inf/lib 下,這些類包是: common-validator.jar 。
這樣,我們就可以使用 struts 的 validation 框架了。
使用 validation 框架
????? 問題
?????? 這是一個簡單的用戶管理程序,使用者可以對用戶信息進行相應的 CRUD 操作(增查改刪)。其中用戶信息包含用戶名稱、用戶地址、用戶描述、用戶密碼。對于以上的各種操作,約束如下:
-????????? 增加和修改:用戶名稱、用戶地址、用戶密碼、用戶密碼確認為必填項,同時密碼和確認密碼 2 個域的值必須一致。
-????????? 刪除和查詢:用戶名稱為必填項。
解決和使用步驟
1.?????? 創(chuàng)建 struts 項目的基本環(huán)境。
2.?????? 創(chuàng)建相應的頁面,確定頁面流程( page flow )。
3.?????? 創(chuàng)建相應的 formbean :
2??????? strut1.1 版本解決辦法:
為了簡單起見使用 DynaActionForm 。又由于使用了 validation 框架,此處使用 DynaValidatorForm 。 struts-config.xm 的內容:
<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 文件內容,其中 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)建相應的 Action ,同時 Action 的 validate 屬性置為 true ,以啟用 validation 框架。
5.?????? 書寫 ApplicationResources.properties ,添加錯誤信息。
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.?????? 在相應的 jsp 中添加 <html:errors property="age"/>
從整個使用過程來看,就驗證部分而言,使用 struts1.1 的開發(fā)效率大大的得到了提高,而且通過 validator-rules.xml 使驗證方法能被不同的 formbean 復用,而且可維護性也大大的得到提高。通過 mask ,使得單個頁面域的驗證非常靈活。
但是細心的讀者可能也發(fā)現了這個驗證文件僅僅指明 2 個 password 域是必填的,但并沒有滿足他們必須是相等的這種情形的判斷,對于這一點,我們可使用自定義的 validator 并將它添加到 validator-rules.xml 文件中來完成。
創(chuàng)建自定義的 validator
?????? 對于 validator 的創(chuàng)建,可以歸結為 3 步:
1.?????? 創(chuàng)建 validator 類, validator 必須包含一個以 validate 開始的方法,并且它的函數簽名必須如下:
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 個域的相等性檢查):
????????????? 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" />
??????????????????
在對應的屬性文件中添加對應的消息(
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
框架的可擴展性大大的得到提高。而且也使得不同的驗證方法能夠很好的得到復用
javascript 支持
?????? 在 web 應用中,使用 javascript 的機會非常多。雖然不少書上提及客戶有可能從瀏覽器關閉 js 的執(zhí)行,但是要想完全的不使用它,目前看來好像還不行。比如一些復雜的 UI 是必須通過 js 來實現的(如下拉式菜單等等)。那么 validation 框架支不支持客戶端的 js 驗證呢?
答案是:當然。具體做法是:
-????????? 在頁面 html:form 標簽內部添加 onsubmit="return validateEditForm(this);" (具體的語法: validate+ 在 validation.xml 文件中定義的 form 的名字);如:
<html:form action="<%=action%>" method="post" onsubmit="return validateEditForm(this);">
-?????????
在
html:form
內部塊中添加:
<html:javascript formName="editForm"/>
?????? 如此 2 步即可。雖然, validation 框架非常簡單易用,但是還是有需要注意的地方。
使用注意
1.?????? 使用 validation 框架后, form 必須從 ValidatorForm 中派生,同時必須在你的 validate 方法中先調用基類的 validate 方法。對于使用 Dyna 開頭的方法來創(chuàng)建 formbean 的讀者,你也必須改為以 dyna 開頭含有 validator 的 form 。
2.?????? 注意 DynaValidatorForm ( ValidatorForm )和 DynaValidatorActionForm ( ValidatorActionForm )的區(qū)別。剛開始時從幫助中沒看明白這 2 者的區(qū)別,后來從網上一篇文章中得到了用法的區(qū)別。前者主要的視角是 formbean ,而后者的視角是 action 。
當 formbean 被不同的 action 使用時,對于不同的 action 而言,使用的 formbean 的屬性集合有大有小。此時如果仍然以 formbean 為主體,會造成其他 action 的不正常使用。因此, struts 中提出了 DynaValidatorActionForm ( ValidatorActionForm )。此時在 validation.xml 中的 form 標簽的 name 屬性改為 action 的 path 屬性,又由于 action 中有 attribute 和 name 屬性, validation 框架就可根據這個 action 得到對應的 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 使得相關的 Action 的關系緊密,大大減少了應用中 Action 的個數,但是隨之而來也帶來了使用 Validation 框架的不便,不能不說是一個遺憾。讀者也許認為這種情況可以使用第 2 條的解決方案來解決,即采用 DyanValidatorActionForm ,然后在 Validation.xml 文件中 form 的名稱使用不同的 Actiond 的 path ,即在 validation.xml 中使用: <form name="/user.do?method=doAdd"> 、 ??? <form name="/user.do?method=doLoad"> 。然而,在目前的版本中 Validation 框架并不支持這種辨認。一種繞過這個情況的方法是,針對同一個 Action 實現類在 Struts-config.xml 文件中定義多個 Action 的 path ,在不需要進行驗證的地方將 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
的方法。
結束語
?????? 總的說來, validation 框架大大的提高了頁面驗證的開發(fā)效率,更吸引人的是這些驗證方法可通過自定義的 validator 來得到復用。使得這些驗證代碼更加集中,可維護性得到加強。當然隨著項目的進行, validation.xml 和 validator-rules.xml 會隨之增長,這部分的維護工作加重了。
?????? 同時,由于不能非常好的和 DispatchAction 一起協作,也使得大量使用 DispatchAction 的項目不能非常好的使用它。建議大量使用 DispatchAction 和頁面驗證非常復雜多變的項目可以暫時按原來的方法來驗證,不使用 validation 框架。
?????? 至于 validation 框架的其他詳細信息,請參見 struts 的文檔,在此不再贅述。
關于作者
胡鍵,西安交通大學工學碩士,熱衷于
j2ee/.net
技術,是
OpenSource
的忠實擁護者。目前與友人創(chuàng)建西安爍程軟件有限公司。公司主要致力于
java web
應用的開發(fā),已有多個項目在能源、電力和交通行業(yè)得到應用。可以通過
james.hu@chinacodeline.com
與他取得聯系。