使用validwhen設計複雜的Struts表單驗證

使用validwhen設計複雜的Struts表單驗證

通過Struts 1.2提供的validwhen 驗證器可以輕鬆的創建更加複雜靈活的表單驗證。

比如說,我們要驗證用戶兩次輸入的密碼是否相同,或是隻有當用戶填寫表單項“姓氏”時,表單項“名字”纔是必須的。

validwhen 需要聲明一個叫testvar字段,這個變量的值是一個布爾型的表達式,比如:

    <var-name>test</var-name>
    <var-value>((orderLines[].partNumber == null) or (*this* != null))</var-value>

當布爾型表達式返回true時,驗證纔會成功。下邊是允許發入該表達式的一些元素:

  • 單引號或雙引號括起來的字符串
  • 十進制、十六進制或八進制表示的整形字面量
  • null 表示沒有輸入的空串
  • 可以使用表單裏的任何字段名字,如 customerAge
  • 顯式引用的索引字段,如childLastName[2]
  • 隱式引用的索引字段,如childLastName[],表示使用與該字段相同的索引
  • 字面量 *this* 表示當前屬性的值

例:

下邊這段代碼表示:只有當sendNewsletter字段爲空,或該字段emailAddress不爲空時,該字段纔有效


<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>

下邊這個例子表示,只有相應的partNumber存在時,字段quantity纔是必須的


下邊這個例子表示,只有相應的partNumber存在時,字段quantity纔是必須的


    <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>

下邊這個例子表示,如果輸入身高小於60英寸,則不能做nbaPointGuard


下邊這個例子表示,如果輸入身高小於60英寸,則不能做nbaPointGuard


    <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>

 

 

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* != nulland (*this*>startDate))</var-value>
                </var>
             </field>

這裏需要注意的是
* <msg>的name屬性的值應該爲某個驗證例程的名稱,例如name="validwhen"、name="date"等,這指明瞭當該field的該驗證例程(本例是validwhendate)出錯時所顯示的錯誤信息。
*如果全局已經定義了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* != nulland (*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}!
發佈了28 篇原創文章 · 獲贊 1 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章