validwhen主要用於關聯驗證,即為了驗證某個域的值,可能會參考其它域的值來進行綜合判斷,以確定該域的值是否符合要求。
1,運算式及其注意事項
輸入給validwhen的是一個布爾型運算式(對該運算式的解析使用了antlr),其引用名為test,即形如:
<var>
<var-name>test</var-name>
<var-value>expression</var-name>
</var>
即,當expression為真(true)時,該域驗證通過,其中,expression可以使用的元素包括:
1)表單中其它域屬性的名稱,例如:
<var>
<var-name>test</var-name>
<var-value>(color=="red")</var-name>
</var>
例子中color為表單中其它某個域的屬性名稱。
2)*this*,用於表示該域的屬性名稱,即對正在驗證的屬性自身,其變數的引用為*this*,例如:
<var>
<var-name>test</var-name>
<var-value>((color=="red") and (*this* != null))</var-name>
</var>
3)可以使用一些常規運算子,如 >、<、==、>=、<=、!=、+、-、*、/、%等等。例如:
<var>
<var-name>test</var-name>
<var-value>((color=="red") and (age>=25))</var-name>
</var>
4)可以使用邏輯運算 and 、or,例如:
<var>
<var-name>test</var-name>
<var-value>(((color=="red") and (age>=25)) or (color!="red"))</var-name>
</var>
在使用and和or時要注意一點,在同一級的邏輯運算中,同時只能存在一個邏輯運算子,要麼是and,要麼是or,即:
xxx and yyy
或者
xxx or yyy
如果在同一級出現多於一個的and或or或and和or的組合,那麼是不合法的,例如下面的運算式是不合法的:
xxx and yyy and zzz
或者
xxx or yyy or zzz
或者
xxx and yyy or zzz
等等
為了讓複雜的表達變得合法,可以讓一個複雜的運算式變為多級的表達形式,每一級只有一個and或一個or就可以了,例如:
xxx and yyy and zzz是錯誤的,進行一下簡單的變換:
(xxx and yyy) and zzz或者xxx and (yyy and zzz)等都是合法的。
5)其他合法的輸入,例如可以使用雙引號和單引號引用literal字串等等。
2,錯誤訊息的定製
無論是validwhen還是其它驗證常式,都可以定製驗證出錯後的錯誤資訊,定製訊息有兩種方式,即全域方式和本地方式。
1)全域方式,即在validator-rules.xml中某個validator裡面定義的訊息,參數名為msg,例如:
<validator name="email" classname="org.apache.struts.validator.FieldChecks" method="validateEmail" methodParams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionMessages, org.apache.commons.validator.Validator, javax.servlet.http.HttpServletRequest" depends="" msg="errors.email"/> |
其中,msg的值為resource bundle中的一個屬性名稱
。例如在resource bundle檔案中存在如下定義:
errors.email={0} is an invalid e-mail address.
2)本地方式,即在validation.xml中的field中定義的錯誤訊息,格式為:
<msg name="validatorName" key="value" resource="booleanValue"/>
例如:
<field property="endDate" depends="validwhen,date"> <msg name="validwhen" key="date.validwhen"/> <arg0 key="start time" resource="false"/> <arg1 key="end time" resource="false"/> <var> <var-name>test</var-name> <var-value>((*this* != null) and (*this*>startDate))</var-value> </var> </field> |
這裡需要注意的是
* <msg>的name屬性的值應該為某個驗證常式的名稱,例如name="validwhen"、name="date"等,這指明了當該field的該驗證常式(本例是validwhen、date)出錯時所顯示的錯誤資訊。
*如果全域已經定義了msg的資訊,而且本地的msg的key與全域的msg的key相同,那麼在該field的驗證中,本地的msg將覆蓋全域的msg。
*<arg0>到<arg4>的屬性中也有name屬性,即該arg參數所應用的驗證常式,例如<arg0 name="date" key="label.startDate"/>,即該參數用於date驗證的出錯資訊。注意,對於一個field,需要的驗證規則有時不止一個,例如depends="required,date",而多個驗證規則中的每一個都需要出錯時傳入一些參數資訊,如果它們所需要的參數個數、名稱和順序都相同,那麼只要定義<arg0...、<arg1...等等即可。但是如果它們需要的參數的個數、名稱和順序不同怎麼辦,如果我們對於第一個輸入參數只定義一個arg0,那麼這個arg0用於哪個驗證訊息,因此這時必須通過arg標籤的name屬性來表示該參數所服務的驗證。
3,例子
情境:在一個表單中,有兩個文本域,用於得到一個時間段,一個文本域輸入起始日期(startDate),另一個輸入終止日期(endDate)。
約束:日期格式為:年(四位元)-月(兩位元)-日(兩位元),而且終止日期大於起始日期。
根據上述條件,驗證規則如下:
<field property="startDate" depends="date"> <arg0 key="form.date.start"/> <var> <var-name>datePatternStrict</var-name> <var-value>yyyy-MM-dd</var-value> </var> </field> <field property="endDate" depends="validwhen,date"> <msg name="validwhen" key="date.validwhen"/> <arg0 name="validwhen" key="form.date.start"/> <arg1 name="validwhen" key="form.date.end"/> <arg0 name="date" key="form.date.end"/> <var> <var-name>test</var-name> <var-value>((*this* != null) and (*this*>startDate))</var-value> </var> <var> <var-name>datePatternStrict</var-name> <var-value>yyyy-MM-dd</var-value> </var> </field> |
在資源檔中加入如下message:
form.date.start=起始日期
form.date.end=終止日期
date.validwhen= {0}不能大於{1}!