傳統 required、mask 等驗證器只能處理單一欄位規則。實務上常見需求:
validwhen 以布林運算式表達跨欄位條件,極大擴展驗證表達力。
在 validation.xml 定義 var 名為 test,值為布林運算式:
<field depends="validwhen" property="emailAddress">
<var>
<var-name>test</var-name>
<var-value>((sendNewsletter == null) or (*this* != null))</var-value>
</var>
</field>
| 符號 | 含義 | 範例 |
|---|---|---|
*this* | 當前被驗證欄位的值 | *this* != null |
fieldName | 表單其他欄位值(同層級) | sendNewsletter == null |
fieldName[index] | 顯式索引陣列欄位 | childLastName[2] |
fieldName[] | 隱式索引(與當前欄位同索引) | orderLines[].partNumber |
null | 空字串或未輸入 | partNumber == null |
| 字串常值 | 單/雙引號括起 | status == 'active' |
| 數值常值 | 十/十六/八進位 | age > 18 |
| 運算子 | and or not = != > < >= <= | (a = 1) and (b != null) |
<field depends="validwhen" property="emailAddress">
<var-value>(sendNewsletter == null) or (*this* != null)</var-value>
</field>
邏輯:未勾選訂閱(sendNewsletter == null)或 Email 已填 → 驗證通過。否則失敗。
<field depends="validwhen" property="quantity" indexedListProperty="orderLines">
<var-value>(orderLines[].partNumber == null) or (*this* != null)</var-value>
</field>
indexedListProperty 指定父層集合屬性,orderLines[].partNumber 表示同一索引的產品編號。邏輯:該行無產品編號 或 數量已填 → 通過。
<field depends="validwhen" property="nbaPointGuard">
<var-value>(heightInInches >= 60) or (*this* == null)</var-value>
</field>
邏輯:身高達標 或 未選擇該角色 → 通過。若身高 < 60 卻勾選 → 失敗。
(A = 'X' and B != null) or (A != 'X' and *this* == null)validwhen 判斷是否需驗證,再 mask 檢查格式parent[].child[].field 需對應 indexedListProperty 層層設定validate() 方法或註解 @Validations@Valid + JSR-303 Bean Validation,自訂 ConstraintValidator 實現跨欄位邏輯validwhen 以聲明式布林運算式解決條件式驗證,減少 Java 代碼量。掌握 *this*、索引引用、null 語意是關鍵。雖 Struts 1 已淘汰,但其設計思想在現代驗證框架中依然可見。