struts2提供了通過XML方式對輸入數據進行驗證的校驗框架。
在與XXXAction同級的目錄下,建立XXXAction-validation.xml,即為該Action的校驗邏輯。
該校驗XML的dtd格式文件為 http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd,具 體內容可以展開下面的代碼:
<?xml version="1.0" encoding="UTF-8"?>
<!--
XWork Validators DTD.
Used the following DOCTYPE.
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
-->
<!ELEMENT validators (field|validator)+>
<!ELEMENT field (field-validator+)>
<!ATTLIST field
name CDATA #REQUIRED
>
<!ELEMENT field-validator (param*, message)>
<!ATTLIST field-validator
type CDATA #REQUIRED
short-circuit (true|false) "false"
>
<!ELEMENT validator (param*, message)>
<!ATTLIST validator
type CDATA #REQUIRED
short-circuit (true|false) "false"
>
<!ELEMENT param (#PCDATA)>
<!ATTLIST param
name CDATA #REQUIRED
>
<!ELEMENT message (#PCDATA)>
<!ATTLIST message
key CDATA #IMPLIED
>
可以看到,數據校驗XML的根元素<validator>下面可以包含兩種 子元素:field和 validator
1、前者field 是針對字段進行的校驗;
2、後者validator 是非字段或者說全局范圍的校驗。
在介紹完校驗是怎麼回事後,後面會簡單比較一下兩種校驗方式的區別。
一、字段校驗:(field)
先看個基本示例
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="error.username.required"/>
</field-validator>
</field>
<field name="password">
<field-validator type="stringlength">
<param name="trim">true</param>
<param name="minLength">4</param>
<param name="maxLength">10</param>
<message>password should be ${minLength} to ${maxLength} characters long.</message>
</field-validator>
</field>
</validators>
有幾個地方需要注意一下的。
1、field-validator的type在哪裡定義的?
struts2校驗框架預設的類在包com.opensymphony.xwork2.validator.validators中,同一目錄下的 default.xml中定義了field-validator中type的名稱和對應的處理類。
default.xml
<!-- START SNIPPET: validators-default -->
<validators>
<validator name="required" class="com.opensymphony.xwork2.validator.validators.RequiredFieldValidator"/>
<validator name="requiredstring" class="com.opensymphony.xwork2.validator.validators.RequiredStringValidator"/>
<validator name="int" class="com.opensymphony.xwork2.validator.validators.IntRangeFieldValidator"/>
<validator name="double" class="com.opensymphony.xwork2.validator.validators.DoubleRangeFieldValidator"/>
<validator name="date" class="com.opensymphony.xwork2.validator.validators.DateRangeFieldValidator"/>
<validator name="expression" class="com.opensymphony.xwork2.validator.validators.ExpressionValidator"/>
<validator name="fieldexpression" class="com.opensymphony.xwork2.validator.validators.FieldExpressionValidator"/>
<validator name="email" class="com.opensymphony.xwork2.validator.validators.EmailValidator"/>
<validator name="url" class="com.opensymphony.xwork2.validator.validators.URLValidator"/>
<validator name="visitor" class="com.opensymphony.xwork2.validator.validators.VisitorFieldValidator"/>
<validator name="conversion" class="com.opensymphony.xwork2.validator.validators.ConversionErrorFieldValidator"/>
<validator name="stringlength" class="com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator"/>
<validator name="regex" class="com.opensymphony.xwork2.validator.validators.RegexFieldValidator"/>
</validators>
<!-- END SNIPPET: validators-default -->
其中,name是上面type需要引用的名字,而後面的class則是這些validator對應的類。這些類中大部 分都是自解釋的,其中fieldexpression比較特殊,它提供了一種多個field之間比較值的機制。
2、param的值又是在哪裡找到的呢?
param中的name值在上述類中被定義為屬性。譬如說在類 com.opensymphony.xwork2.validator.validators.StringLengthFieldValidator中(也就是 stringLength對應的處理類),就定義了
boolean trim;
int minLength,maxLength;
及它們的get/set方法。
3、message的注意事項
(1)每個field都必須擁有一個message;message錯誤信息最後是以addFieldError實現的,也就是說是 field一級的錯誤。
(2)message中可以引用param變量,引用格式為${param1},如上面的例子中對password驗證失敗的報錯 信息。
(3)message的內容可以放到全局i18n屬性文件中,並在message中以key屬性值指定,比如上面例子中 對username驗證失敗的報錯信息。
二、非字段校驗/全局校驗
全局校驗和字段校驗其實類似,使用的驗證器也是那些。區別在於校驗的方式和關注點不同:
1、字段校驗先指定那個字段要校驗,再指定用那些校驗器來校驗該字段;
2、全局校驗不針對特定字段,先指定驗證器,再來指定用該校驗器校驗那些字段。
基本示例如下:
<validators>
<validator type="requiredstring" short-circuit="true">
<param name="fieldName">username</param>
<param name="fieldName">password</param>
<param name="fieldName">password_confirmed</param>
<message key="error.field.required"/>
</validator>
<validator type="stringlength">
<param name="trim">true</param>
<param name="minLength">4</param>
<param name="maxLength">10</param>
<param name="fieldName">password</param>
<param name="fieldName">password_confirmed</param>
<message>password should be ${minLength} to ${maxLength} characters long.</message>
</validator>
</validators>
示例很簡單,第一個validator是校驗“不為空的字符串”,校驗“用戶名”、“密碼”、“確認密碼 ”字段,第二個校驗器校驗“字符串長度6-10”,校驗“密碼”、“確認密碼”兩個字段。
很明顯,如果頁面中存在一些共性的驗證要求,用這種方式就比針對字段的驗證要方便。但這種方式 可能不如前一種方式清晰易讀。
兩種驗證方式可以混用。
三、其他問題
1、對多驗證和跳轉邏輯的支持
和《Struts2 數據輸入校驗(1) —— 函數驗證 》中所說內容一樣,校驗框架也支持多驗證和跳轉邏 輯。比如說在struts.xml文件中配置了
<action name="XXXAction" class="com.myspace.myname.XXXAction" method="newExcuteName">
<result>success.jsp</result>
</action>
則校驗文件的名字為XXXAction-newExcuteName-validation.xml
當然,在執行了上面的校驗之後,如果存在XXXAction-validation.xml,則還會執行這個文件中定義 的校驗。
同時需要注意的是,如果該Action存在父類,則會先行執行父類的相應校驗。
2、客戶端校驗
客戶端校驗是不安全的,但struts仍然提供了客戶端的校驗
方法是在<s:form>中設置validate屬性為true,如果該屬性被設置,則struts不會在服務器端驗 證,取而代之的是在客戶端生成Javascript代碼。但這些Js代碼功能較弱,靈活度也比較低,且不會刷新 。因此不推薦使用。
其實struts的控件本身和一般的HTML控件一樣,如果想做客戶端驗證,可以觸發它們的onXXX()事件, 和通常的HTML頁面做法一樣。