作者:
David Winterfeldt 大衛(wèi)
James Turner 詹姆斯
Rob Leland 羅伯特
翻譯:
?????? 侯思超
驗證器:
從 0.5 版,驗證器在一些 form 中就已經(jīng)實現(xiàn)了,他最初包含在開發(fā)人員包中,后來核心代碼挪到 Jakarta Commons 包中和 Struts 特別擴展中作為 Struts 1.1 的一部分。許多開發(fā)者為方便一直使用 struts 驗證器,這篇文檔首先概述驗證器的核心功能性,然后大概介紹在 struts1.1 中的變化和新增功能。
如果你配置好驗證器插件,你應該擴展 ValidatorForm 而不是 ActionForm ,以便它能加載你的 Validator 資源。他根據(jù) struts-config.xml 文件中的 action 的 name 屬性為當前 form 的調(diào)用相應的驗證器,因此在 validator-rules.xml 中的 form 元素的名稱屬性應該與 action 的 name 屬性值相匹配。
另外一種選擇是擴展 ValidatorActionForm 而不是 ValidatorForm , ValidatorActionForm 使用 struts-config.xml 中 action 的 path 屬性,所以 path 屬性的值相應的應該與 validator-rules.xml 中的 Form 的 name 屬性匹配。
一個分離的 action 可以定義給多頁 form 的每個頁面,而且驗證規(guī)則可以與 action 關(guān)聯(lián)而不是與頁碼,就像驗證范例中的多頁 form 范例那樣。
國際化
在 validator-rules.xml 文件中 form 的驗證規(guī)則可以組織為 FormSet 。 FormSet 有與 java.util.Locale 類相應的屬性:如語言 , 國家以及變量型屬性,如果他們未定義, FormSet 將把它設置為默認值。一個 FormSet 也可以有關(guān)聯(lián)的常量。另外還可以定義與 FormSet 同一級別的全局 global 元素,他與 FormSet 同樣也有常量。
注意 :你必須在國際化的 FormSet 前聲明一個沒有國際化的默認 FormSet 。這樣如果 Validator 沒有找到 locale 時可以有一個默認版本。
?????? 可插入驗證器的默認錯誤信息值可以被 msg 元素覆蓋。所以為 mask 驗證器生成錯誤信息的替代方法就是使用 msg 屬性,如果字段的 name 屬性與驗證器的 name 屬性匹配,那末將使用字段的 msg 屬性。
?????? error messages 的可以設置 arg0-arg3 等參數(shù)元素。如果沒有設置 arg0-arg3 的 name 屬性, error messages 將使用他們作為默認的構(gòu)建參數(shù)值。如果設置了 name 屬性,你就可以把參數(shù)指定給一特定的可插入驗證器,然后這些參數(shù)將在構(gòu)造錯誤信息時被使用。
<field
property="lastName"
depends="required,mask">
<msg
name="mask"
key="registrationForm.lastname.maskmsg"/>
<arg0 key="registrationForm.lastname.displayname"/>
<var>
<var-name>mask</var-name>
<var-value>^[a-zA-Z]*$</var-value>
</var>
</field>
默認的 arg0-arg3 元素將在消息資源中查找相應的 key ,如果資源屬性設為 false ,她將把值直接傳進去,而不從消息資源中查找。注意 1.1 版本中,你必須為每個模塊中明確地定義在驗證中用到的消息資源,否則將使用 top-level 資源。
<field
property="integer"
depends="required,integer,intRange">
<arg0 key="typeForm.integer.displayname"/>
<arg1
name="range"
key="${var:min}"
resource="false"/>
<arg2
name="range"
key="${var:max}"
resource="false"/>
<var>
<var-name>min</var-name>
<var-value>10</var-value>
</var>
<var>
<var-name>max</var-name>
<var-value>20</var-value>
</var>
</field>
常量 / 變量
全局的常量可以在全局標簽中定義, FormSet/ 本地常量能在 formset 標簽中創(chuàng)建。常量當前僅僅是代替字段的 property 屬性,字段的 var 元素的 value 屬性,字段的 msg 元素的 key 屬性,字段的 arg0-arg3 元素的 key 屬性。字段的變量也可以在 arg0-arg3 元素中被代替(例如: ${var:min} ))。替換的順序是 FormSet/Locale 常量第一,全局的常量第二,
arg elements 變量最后。
<global>
<constant>
<constant-name>zip</constant-name>
<constant-value>^\d{5}(-\d{4})?$</constant-value>
</constant>
</global>
?
<field
property="zip"
depends="required,mask">
<arg0 key="registrationForm.zippostal.displayname"/>
<var>
<var-name>mask</var-name>
<var-value>${zip}</var-value>
</var>
</field>
驗證器可以使用字段下面的變量部分來存儲變量,這些變量通過字段的 getVar ( (String key) 方法取得。
<field
property="integer"
depends="required,integer,intRange">
<arg0 key="typeForm.integer.displayname"/>
<arg1
name="range"
key="${var:min}" resource="false"/>
<arg2
name="range"
key="${var:max}" resource="false"/>
<var>
<var-name>min</var-name>
<var-value>10</var-value>
</var>
<var>
<var-name>max</var-name>
<var-value>20</var-value>
</var>
</field>
使用 validwhen 設計復雜的驗證
使用 validwhen 來設計復雜驗證的一個經(jīng)常的要求就是根據(jù)一個字段驗證另外一個字段(比如 , 如果你要用戶兩次輸入口令來確認值口令一致),另外一個就是表單中的一個字段只有另外一個字段有確定值的時候才是必須輸入的。新的 validwhen 驗證規(guī)則將很快被包含在 1.1 后的 STRUTS 版本中,她就是用來處理這種情況的。
?????? validwhen 規(guī)則處理單個的變量字段,叫測試。這變量的值是一個布爾的表達式,如果驗證有效則它必須為真。可以包含這種變量的表達式有:
u?????? 單引號或雙引號字符串 literals ,
u?????? 十進制、十六進制、八進制的 Integer literals ,
u?????? null 與 null 和空字符串匹配,
u?????? 其它可以用屬性名引用的 form 字段 , 例如 customerAge ,
u?????? 可以在外部因用得索引字段 , 例如 childLastName[2] ,
u?????? 可以默認 implicit 因用得索引字段 , 例如 childLastName[], 她將作為被索引的字段使用同樣的索引到數(shù)組中,
The literal *
這里指它包含當前測試字段的值,
作為例子,考慮一個包含通訊地址和郵箱字段的 form 。如果通訊地址不為空則郵箱字段是必須的 required 。你能這樣定義 validwhen 規(guī)則:
<field property="emailAddress" depends="validwhen">
<arg0 key="userinfo.emailAddress.label"/>
<var>
<var-name>test</var-name>
<var-value>((sendNewsletter == null) or (*this* != null))</var-value>
</var>
</field>
上面定義的意思是:如果通訊地址是空或不空時這個字段時有效的。
這里有個稍微復雜的例子,它使用了索引字段。假定有一個表單,允許用戶輸入他們希望定購的部件號和數(shù)量。類 orderLine 的 bean 的一數(shù)組被用來在稱為 orderLines 的一屬性保持輸入項。
If you wished to verify that every line with part number also had a quantity entered, you could do it with:
如果你希望校驗訂單中有數(shù)量輸入得每一行,你可以這樣:
<field
property="quantity"
indexedListProperty="orderLines"
depends="validwhen">
<arg0 key="orderform.quantity.label"/>
<var>
<var-name>test</var-name>
<var-value>((orderLines[].partNumber == null) or (*this* != null))</var-value>
</var>
</field>
這里的意思是:如果相應的 partNumber 字段是空 , 或這字段是不空的,則這字段是有效的。
最后一個例子,想象一表單,用戶必須輸入他們的以英寸為單位的高度,如果他們在高度在 60 英寸以下,則出一錯誤。( it is an error to have checked off nbaPointGuard as a career. )
<field property="nbaPointGuard" depends="validwhen">
<arg0 key="careers.nbaPointGuard.label"/>
<var>
<var-name>test</var-name>
<var-value>((heightInInches >= 60) or (*this* == null))</var-value>
</var>
</field>
?
給程序員的簡單說明:
所有的比較關(guān)系必須在 parens 封裝。 All comparisons must be enclosed in parens.
只有兩個 itme 時可以 and 或 or 鏈接。
如果比較的兩 item 都可以轉(zhuǎn)為整數(shù),則使用 numeric 比較,否則使用字符串比較。
可插入驗證器
驗證是從 validation.xml 文件中加載的,默認的驗證規(guī)則定義在 validation.xml 文件中,默認定義了 required, mask ,byte, short, int, long, float, double, date ( 沒有本地支持 ), and a numeric range 。
" mask " 方式依賴于默認值安裝要求,那意味著 "required " 可以完成,在 "'mask " 將運行以前 "required " 和 " mask " 方式被默認包含進框架中了。任何字段如果不是 "required " 而且是空或有零長度將跳過其他驗證。
如果使用了 Javascript 標簽,客戶端 javascript 在 validator's javascript 屬性中查找值而且產(chǎn)生一個有驗證 form 方法的對象,要得到更多的關(guān)于 Javascript Validator 標簽工作細節(jié)的詳細的解釋 , 參閱 html 標簽 API 參考。
"'mask' " 方式讓你用一正則表達式掩碼驗證字段,它使用 jakarta 的正規(guī)表達式包,所有的有效性規(guī)則存儲在 validator-rules.xml 文件,使用的主類是 org.apache.regexp.RE 。
validation.xml 文件中的驗證器配置范例:
<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">
<validator name="mask"
classname="org.apache.struts.validator.FieldChecks"
method="validateMask"
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.invalid">
?
定義可插入驗證器
方法的參數(shù)是用逗號分隔的一些類名稱列表,方法屬性需要有一個符合上面的列表的簽名。列表由以下組合而成:
java.lang.Object – 要驗證的 Bean 。
org.apache.commons.validator.ValidatorAction – 當前 ValidatorAction 。
org.apache.commons.validator.Field – 要驗證的字段
org.apache.struts.action.ActionErrors – 如果驗證錯誤將加入 ActionError 的錯誤對象 javax.servlet.http.HttpServletRequest – 當前 request 對象。
javax.servlet.ServletContext – 應用的 ServletContext 。
org.apache.commons.validator.Validator– 當前的 org.apache.commons.validator.Validator 實例。
java.util.Locale – 當前用戶的 Locale 。
多頁面 form
字段部分有一可選的頁面屬性,它可以被設為整數(shù),頁上字段的所有驗證小于或等于服務器端驗證的當前頁,頁上字段的所有驗證小于或等于客戶端頁上所有字段的驗證小于或等于服務器端驗證的當前頁驗證的當前頁。一個 mutli-part 表單需要定義頁面屬性:
<html:hidden property="page" value="1"/> 。
比較兩個字段
這是一個展示你怎樣才能比較兩個字段是否有一樣的值的例子。比如“用戶改變他們的口令“一般會有口令字段和一確認字段。
<validator name="twofields"
classname="com.mysite.StrutsValidator"
method="validateTwoFields"
msg="errors.twofields"/>
<field property="password" depends="required,twofields">
<arg0 key="typeForm.password.displayname"/>
<var>
<var-name>secondProperty</var-name>
<var-value>password2</var-value>
</var>
</field>
?
public static boolean validateTwoFields(
Object bean, ValidatorAction va,?
Field field, ActionErrors errors, HttpServletRequest request,?
ServletContext application) {
String value = ValidatorUtils.getValueAsString( bean,? field.getProperty());
String sProperty2 = field.getVarValue("secondProperty");
String value2 = ValidatorUtils.getValueAsString( bean,? sProperty2);
?
?????? if (!GenericValidator.isBlankOrNull(value)) {
try {
if (!value.equals(value2)) {
errors.add(field.getKey(),
Resources.getActionError( application, request, va, field));
???????????????????? ?????? return false;
}
} catch (Exception e) {
errors.add(field.getKey(), Resources.getActionError( application, request, va, field));
return false;
}
}
}
已知的 bug
Struts Validator 依賴于 Commons Validator 包,所以問題報告和增強需求可能在兩個產(chǎn)品中列出。
·?? Struts Validator Bugzilla Reports
·?? Commons Validator Bugzilla Reports
變更和 deprecations
新建的標記屬性。
<html:javascript> 標記有新的屬性定義 .
使用
commons-validator.jar
中的
DTD
驗證。
當前使用的驗證 XML 文件是根據(jù) commons-validator.jar 中的 DTD 。 Struts 不在為 validator-rules.xml and validator.xml. 單獨維護一個分離的 DTD ,另外 ,commons-validator 現(xiàn)在維護一個統(tǒng)一的 validator.dtd 。修改所有 validator.xml 文件的 DTD 引用為
<!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">
空字段。
當前默認在所有得基礎驗證類型中忽略空白的字段,如果你要求一個字段必須輸入,那末在你的應用的 validator.xml 文件相應的字段定義的 depends 屬性中添加 " required " 。
新建的范圍
RANGE
方法
.
JavaScript 和 JAVA 中都添加了 intRange & floatRange 方法。
有條件地
REQUIRED
字段
.
最大的修改是添加了基于其她字段的值的有條件地 require 驗證的能力。它允許你定義邏輯如:“只有 X 字段非空的時候 Y 字段為 ’male’ 才有效”,這是實現(xiàn)上述邏輯的推薦方法,這種方法在 1.1 版后的第一版將實現(xiàn)。在 1.1 版中添加的 Requiredif 驗證規(guī)則,將在新版中去掉。不過,如果你正準備使用 requiredif ,這里有一個簡短的教程。
?????? 讓我們假定你有一個有 3 個字段的醫(yī)藥的信息表單,性別 sex ,懷孕測試 pregnancyTest ,測試結(jié)果 testResult ,如果性別為 'f' or 'F' ,則懷孕測試 pregnancyTest 是 required ,如果 pregnancyTest 不是空,測試結(jié)果 testResult 是 required 。
你的 validation.xml 文件的輸入項應該是這樣的:
<form name="medicalStatusForm">
<field property="pregnancyTest" depends="requiredif">
<arg0 key="medicalStatusForm.pregnancyTest.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>sex</var-value>
</var>
<var>
<var-name>fieldTest[0]</var-name>
<var-value>EQUAL</var-value>
</var>
<var>
<var-name>fieldValue[0]</var-name>
<var-value>F</var-value>
</var>
<var>
<var-name>field[1]</var-name>
<var-value>sex</var-value>
</var>
<var>
<var-name>fieldTest[1]</var-name>
<var-value>EQUAL</var-value>
</var>
<var>
<var-name>fieldValue[1]</var-name>
<var-value>f</var-value>
</var>
<var>
<var-name>fieldJoin</var-name>
<var-value>OR</var-value>
</var>
</field>
<field property="testResult" depends="requiredif">
<arg0 key="medicalStatusForm.testResult.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>pregnancyTest</var-value>
</var>
<var>
<var-name>fieldTest[0]</var-name>
<var-value>NOTNULL</var-value>
</var>
</field>
</form>
?
這里有一個使用索引的屬性更復雜的例子,如果你的 struts-config.xml 有這下面:
<form-bean name="dependentlistForm"
type="org.apache.struts.webapp.validator.forms.ValidatorForm">
<form-property
name="dependents"
type="org.apache.struts.webapp.validator.Dependent[]" size="10"/>
<form-property name="insureDependents" type="java.lang.Boolean" initial="false"/>
</form-bean>
這里 dependentlistForm bean 有 lastName , firstName , dob , coverageType 四個屬性,你可以這樣定義一驗證規(guī)則:
<form name="dependentlistForm">
<field
property="firstName" indexedListProperty="dependents" depends="requiredif">
<arg0 key="dependentlistForm.firstName.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>lastName</var-value>
</var>
<var>
<var-name>fieldIndexed[0]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>fieldTest[0]</var-name>
<var-value>NOTNULL</var-value>
</var>
</field>
?
<field
property="dob" indexedListProperty="dependents" depends="requiredif,date">
<arg0 key="dependentlistForm.dob.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>lastName</var-value>
</var>
<var>
<var-name>fieldIndexed[0]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>fieldTest[0]</var-name>
<var-value>NOTNULL</var-value>
</var>
</field>
?
<field
property="coverageType" indexedListProperty="dependents" depends="requiredif">
<arg0 key="dependentlistForm.coverageType.label"/>
<var>
<var-name>field[0]</var-name>
<var-value>lastName</var-value>
</var>
<var>
<var-name>fieldIndexed[0]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>fieldTest[0]</var-name>
<var-value>NOTNULL</var-value>
</var>
<var>
<var-name>field[1]</var-name>
<var-value>insureDependents</var-value>
</var>
<var>
<var-name>fieldTest[1]</var-name>
<var-value>EQUAL</var-value>
</var>
<var>
<var-name>fieldValue[1]</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>fieldJoin</var-name>
<var-value>AND</var-value>
</var>
</field>
</form>
這里的意思是:
如果 lastName 字段是非空的, firstName 字段 required 。因為字段 Indexed 為真,這它意味著 lastName 的 indexed 必須與 firstName 的索引的一樣, dob 同理,除非 date 不為空。
如果 lastName 用樣索引時的值不空 , 而且非索引字段 insureDependents 為真,則 coverageType 是 only require 。
你可以對字段在 [n] 中使用任意數(shù)字,唯一的限制是他們必須都是 AND 或 OR, 你無法混合使用。
Deprecation
:
u?????? JavaScript 和 Java 的 range 方法 .
u?????? StrutsValidator &StrutsValidatorUtil 類中的 Deprecation 方法
驗證器 api 指南
一個簡明的 Struts驗證器API指南 可以幫助你開始。
驗證器資源
Struts Validator: Validating Two Fields Match 作者Matt Raible。(兩個字段匹配驗證)關(guān)于使用方法的文章。(范例部分為翻譯此文內(nèi)容)
DynaForms and the Validator 作者James Turner and Kevin Bedell。 Struts Kickstart 的其中一章(動態(tài)form和驗證器),可以自由下載PDF).
Validating user input 作者 David Winterfeldt and Ted Husted。 Struts in Action 的其中一章,可以自由下載(PDF)。
使用方法
作者:
丑陋
&& Snowtears
:經(jīng)過
2
周的不懈努力,閱讀了大量的資料,終于對
Validator
有了個初步的認識,整理了一下,淺淺的談了談寫法,希望能有一定的幫助,其中肯定有許多說的不對不準確的地方,還請多指教
real_herozx@163.net
?????? 王藝:
?????? 根據(jù)以上兩位的文章正理而成
配置 ruts-config.xml :
1、 ??????????? 添加 ApplicationResources 配置文件。
如:
<!-- ========== Message Resources Definitions =========================== -->
<message-resources parameter="com.dc.sibss.om.struts.ApplicationResources" />
其中 com.sibss.om.struts.ApplicationResources" 的部分是 資源文件 的路徑,此文件的作用是提供錯誤信息的非編程定制化和多語言支持。如果我們使用中文平臺操作系統(tǒng),則默認情況下將首先查找 ApplicationResource_zh_CN.properties 文件,然后是 ApplicationResources_zh.properties ,如果前兩個文件沒有被找到則將查找 ApplicationResources.properties 文件。
為了能夠在頁面上顯示錯誤提示信息,我們還需要將以下內(nèi)容添加到 ApplicationResources.properties 文件的末尾:
?????? ?????? errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be an byte.
errors.short={0} must be an short.
errors.integer={0} must be an integer.
errors.long={0} must be an long.
errors.float={0} must be an float.
errors.double={0} must be an double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
以上僅是 struts 現(xiàn)在支持的錯誤類型的錯誤提示信息,如果你自定義了新類型的錯誤驗證,則還需要在此加上你自己的內(nèi)容。
以上內(nèi)容中的 {0} 指的是錯誤提交的參數(shù)。比如:當你需要頁面上的“用戶名”不能為空時(也就是上面的 errors.required ),這個 {0} 就代表“用戶名”,所以如果你沒有填寫用戶名將拋出如下錯誤:
??????
用戶名
is required.
(你可以根據(jù)需要修改稱中文)
我們可能已經(jīng)注意到了,既然錯誤提示信息需要配置,那么上例中“用戶名”系統(tǒng)是如何得到的呢?沒錯!也是通過修改此配置文件,內(nèi)容如下:
?????? visitCust.error.name.required=<br> 用戶名
這樣當“用戶名”為空時, struts 后臺程序?qū)⒙?lián)合以上兩處定義顯示錯誤信息。
另外,上面的“ visitCust.error.name.required ”是在 Validation.xml 配置驗證內(nèi)容時指定的。 具體見以下介紹 。
注意:一般情況下,你的系統(tǒng)只需要一個 ApplicationResources 文件,所以開發(fā)組的成員不要添加自己的 resource 文件。只有在你的項目分組開發(fā)時才需要使用多個 ApplicationResources 文件,但是,同時你的 struts-config.xml 文件也會有相同的數(shù)量對應。
2、 ??????????? 在 struts-config.xml 文件中加入 validator 插件:
加入這個插件后你的應用就具備使用 Validator 的環(huán)境,如:
<!-- ========== Plug Ins Configuration ================================== -->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" property="pathnames" />
</plug-in>
這里如果是想使用多個 ***.xml 文件的話, value 部分寫法如下 value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml, /WEB-INF/validation1.xml , /WEB-INF/validation2.xml "
在 <action-mappings> 里,定義需要驗證的畫面對應的 Action 的時候要加上 validate="true"
四種使用方法
1、 ??????????? 用 Javascript 在客戶端進行驗證
配置:在需要驗證的 JSP 文件中寫入
<html:form action="/XXX" onsubmit="return validateXXXX(this);">
這里的 XXX 是與要進行驗證的 forward name , validateXXXX (this); 里面的 XXXX 是需要進行驗證的 ActionForm 名。
<html:javascript formName="mytestForm"/>
在 validation.xml 文件中寫入驗證代碼就可以進行基本的驗證了。這種方法是在客戶端進行驗證,客戶端可以看到 JAVASCRIPT 部分的全代碼。安全性不高
2、 ??????????? ValidatorForm 的 validate 方法
1 、 validate ()方法: 使自己的 ActionForm 繼承 ValidatorForm 類,在里面編寫自己的方法:
public ActionErrors validate (ActionMapping mapping,HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
。。。。。。
if ( mytext.equals("aaa") ) {
//my exampleerrors.add("mytext",new ActionError("mytext.error"));
}
。。。。。。
return errors;
}
此時,如果寫了這個方法,就會屏蔽掉在 Validation.xml 中定義的驗證部分,換句話說就是系統(tǒng)運行時, Validation.xml 里對應此 ActionForm 的定義的錯誤驗證部分不實行,如果不寫這個方法的話,系統(tǒng)運行時會進行 Validation.xml 里對應此 ActionForm 的定義的錯誤驗證部分的操作。此類方法是在服務器端進行驗證,驗證部分代碼客戶端不可見。
2 、創(chuàng)建你的 ActionForm 并讓它繼承 org.apache.struts.validator.ValidatorForm 類。創(chuàng)建你的 Action 實現(xiàn),并和上面定義的 ActionForm 關(guān)聯(lián)。這里需要注意的是,在定義此 Action 時一定將 validate 屬性設置為 true ,并且在你定義的 ActionForm 中不要實現(xiàn)它的 validate 方法――這就意味著你將使用 ValidatorForm 的 validate 方法,這樣才能保證你的錯誤驗證正常進行。 配置 validation.xml 文件。基本內(nèi)容如下:
<form-validation>
<!-- ========== Default Language Form Definitions ===================== -->
??? <formset>
?????? ?????? <form name="custGNewForm"> 需要驗證頁面上 form 的名字
????????????? ?????? <field property="certifiCode" 需要校驗的屬性
????????????? ????????????? ?????? depends="required,maxlength"> 校驗內(nèi)容
????????????? ?????? ?????? <arg0 key="prompt.certifiCode"/>ApplicationResource 文件中對應
????????????? ?????? ?????? <arg1 key="${var:maxlength}" name="maxlength" resouce="false"/>
????????????? ?????? ?????? <var> 確定最長限制的長度
????????????? ????????????? ?????? <var-name>maxlength</var-name>
????????????? ????????????? ?????? <var-value>20</var-value>
????????????? ?????? ?????? </var>
????????????? ?????? </field>
注意:此處的
arg0
和
arg1
就代表了
ApplicationResources
文件中使用“
{}
”括起來的參數(shù)。比如:
errors.range={0} is not in the range {1} through {2}.
定義了三個參數(shù),所以你這里也要定義
<arg0>
、
<arg1>
、
<arg2>
三個參數(shù)才能完整的顯示錯誤信息。
errors.maxlength={0} cannot be greater than {2} characters.
定義了
0
、
2
兩個參數(shù),所以你就需要定義
<arg0>
和
<arg2>
兩個參數(shù)。
????????????? ?????? <field ?????? property="userName"
????????????? ????????????? ?????? depends="required,maxlength">
????????????? ?????? ?????? <arg0 key="prompt.userName"/>
????????????? ?????? ?????? <arg2 key="${var:maxlength}" name="maxlength" resouce="false"/>
????????????? ?????? ?????? <var>
????????????? ????????????? ?????? <var-name>maxlength</var-name>
????????????? ????????????? ?????? <var-value>80</var-value>
????????????? ?????? ?????? </var>
????????????? ?????? </field>
????????????? ?????? <field property="email"
??????????????????? depends="email">
??????????????? <arg0 key="prompt.email"/>
??????????? </field>
?????? ?????? </form>
?????? ?????? <form name="custGNewCheckForm">
????????????? ?????? <field?????? property="certifiCode"
????????????? ????????????? ?????? depends="required">
????????????? ?????? ?????? <arg0 key="prompt.certifiCode"/>
????????????? ?????? </field>
?????? ?????? </form>
??? </formset>
</form-validation>
在校驗頁面的 <body> 前添加如下內(nèi)容: <html:errors/>
3、 ??????????? DynaValidatorForm
不需要再寫對應的 ActionForm ,只需在 struts-config.xml 里把自己的 ActionForm 進行配置:
<form-bean name="testForm" type="org.apache.struts.validator. DynaValidatorForm">
?????? <form-property name="mytext" type="java.lang.String"/>
<form-property name="mytextarea" type="java.lang.String"/>
?????? <form-property name="mydatetext" type="java.lang.String"/>
</form-bean>
在 form-property 里設置相應的項目,比如說 mytext , mytextarea 什么的,執(zhí)行的時候會動態(tài)生成 ActionForm ,再在 validation.xml 里寫入所希望的驗證代碼,就可以了。 JSP 文件里不需要寫入任何東西,驗證也是在服務器端進行,驗證部分代碼在 JSP 中不可見。
4、 ??????????? 組合驗證
如果使用動態(tài)驗證 DynaValidatorForm 的話,不許編寫自己的 對應的 ActionForm ,相應的特殊驗證會受到相當程度的限制。這個時候,需要將特殊驗證部分寫入對應的 Action ,
if(mytext.equals("aaa")){//My Example
ActionErrors errors = new ActionErrors();
errors.add("***",new ActionError("***.error"));??????
saveErrors(request,errors);
return (mapping.findForward("false"));
}
就可以實現(xiàn)特殊驗證了。
?
?????? 實際上你的 FORM 還可以繼承 ValidatorActionForm 和 DynaValidatorActionForm ,這兩種與他們對應的 ValidatorForm 和 DynaValidatorForm 的唯一區(qū)別正如開篇就講到的:在 struts-config.xml 中查找對應的 FORM 類時,前者根據(jù) ACTION 的 PATH 值,而后者使用 NAME 值。
范例:
Struts
驗證器:驗證兩個字段匹配
在使用指南中,有一節(jié)講述怎樣創(chuàng)建驗證器來驗證兩個字段匹配,我用這個服務器端驗證器(象例子中顯示的那樣)做口令,確定口令驗證。這個已經(jīng)可以正常工作了;但我還想用客戶端的
javascript
驗證器來試一試。我寫了自己的程序來比較兩個字段,但他們和推薦給你的那個不同(
from
validator-rules.xml
)。所以昨天,我補充了怎樣添加
JavaScript
方法到
validator-rules.xml
。
這里就是怎樣配置的的整個過程(大部分在使用指南中已經(jīng)包含了,保存
JavaScript
)。
怎樣添加兩個字段的驗證器
Step 1:
生成一個包含
validateTwoFields
方法的
類。在我的代碼重,我的類定義為
ValidationUtil
,他有下列方法:
?
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;
}
Step 2:
編輯
validator-rules.xml
,加入
"twofields"
規(guī)則。
<validator name="twofields" classname="org.appfuse.webapp.util.ValidationUtil"
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"
?? depends="required" msg="errors.twofields">
??? <javascript><![CDATA[
??????? function validateTwoFields(form) {
??????????? var bValid = true;
??????????? var focusField = null;
??????????? var i = 0;
??????????? var fields = new Array();
??????????? oTwoFields = new twofields();
??????????? for (x in oTwoFields) {
??????????????? var field = form[oTwoFields[x][0]];
??????????????? var secondField = form[oTwoFields[x][2]("secondProperty")];
???????????
??????????????? if (field.type == 'text' ||
??????????????????? field.type == 'textarea' ||
??????????????????? field.type == 'select-one' ||
??????????????????? field.type == 'radio' ||
??????????????????? field.type == 'password') {
???????????
??????????????????? var value;
??????????????????? var secondValue;
??????????????????? // get field's value
??????????????????? if (field.type == "select-one") {
??????????????????????? var si = field.selectedIndex;
? ?????????????????????? value = field.options[si].value;
??????????????????????? secondValue = secondField.options[si].value;
??????????????????? } else {
??????????????????????? value = field.value;
??????????????????????? secondValue = secondField.value;
??????????????????? }
???????????????
??????????????????? if (value != secondValue) {
???????????????????
??????????????????????? if (i == 0) {
??????????????????????????? focusField = field;
??????????????????????? }
??????????????????????? fields[i++] = oTwoFields[x][1];
??????????????????????? bValid = false;
??????????????????? }
??????????????? }
??????????? }
???????????
??????????? if (fields.length > 0) {
??????????????? focusField.focus();
??????????????? alert(fields.join('\n'));
??????????? }
???????????
??????????? return bValid;
??????? }]]></javascript>
</validator>
Step 3:
在
validation.xml
中
為你的表單配置驗證:
<field property="password" depends="required,twofields">
? <msg name="required" key="errors.required"/>
? <msg name="twofields" key="errors.twofields"/>
? <arg0 key="userForm.password"/>
? <arg1 key="userForm.confirmPassword"/>
? <var>
??? <var-name>secondProperty</var-name>
??? <var-value>confirmPassword</var-value>
? </var>
</field>
這里
errors.twofields
的
字段
'{0}'
必須與字段
'{1}'
的值相同。第三步的一個可選的工作就時使用
XDoclet
來生成
validation.xml
。
requires (1)
配置
XDoclet (
當然
)
和
(2)
在你的表單中添加添加一些
@struts
標簽
setPassword
方法
。
/**
?* Returns the password.
?* @return String
?*
?* @struts.validator type="required" msgkey="errors.required"
?* @struts.validator type="twofields" msgkey="errors.twofields"
?* @struts.validator-args arg1resource="userForm.password"
?* @struts.validator-args arg1resource="userForm.confirmPassword"
?* @struts.validator-var name="secondProperty" value="confirmPassword"
?*/
public String setPassword() {
?????? return password;
}
我昨天已經(jīng)把這個作為建議發(fā)送給struts-dev郵件列表, 但還沒有收到任何消息。