[標題]:[原]Struts2校驗框架
[時間]:2009-7-27
[摘要]:校驗框架配置、客戶端校驗
[關鍵字]:浪曦視頻,Struts2應用開發(fā)系列,WebWork,Apache,validation
[環(huán)境]:struts-2.1.6、JDK6、MyEclipse7、Tomcat6
[作者]:Winty (wintys@gmail.com) http://www.tkk7.com/wintys

[正文]:
    Struts校驗框架提供了一種不用編寫代碼,只需修改配置文件即可對輸入進行校驗的功能。代碼方式校驗,即重寫validate()方法。實際應用中,validate()與校驗框架一般只選其一

1、校驗框架配置
    在RegisterAction.java相同目錄新建校驗框架配置文件RegisterAction-validation.xml。RegisterAction-validation.xml的DTD可以復制struts自帶的示例struts2-mailreader-2.1.6中的DTD:
<!DOCTYPE validators PUBLIC
          "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
          "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

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
>


RegisterAction-validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
          "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
          "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
 
 <validators>
 <!--  
     與field等價的validator
     <validator type="requiredstring">
         <param name="fieldName">name</param>
         <param name="trim">true</param>
         <message>name required</message>
     </validator>
     <validator type="stringlength">
         <param name="fieldName">name</param>
             <param name="trim">true</param>
             <param name="minLength">6</param>
             <param name="maxLength">10</param>
             <message>name length range : ${minLength} ~ ${maxLength}</message>
     </validator>
 -->    
     <field name="name">
         <field-validator type="requiredstring" >
             <param name="trim">true</param>
             <message>name required</message>
         </field-validator>
         <field-validator type="stringlength">
             <param name="trim">true</param>
             <param name="minLength">6</param>
             <param name="maxLength">10</param>
             <message>name length range : ${minLength} ~ ${maxLength}</message>
         </field-validator>
     </field>
     
     <field name="age">
         <field-validator type="conversion" short-circuit="true">
             <message>the field age conversion error</message>
         </field-validator>
         <field-validator type="int">
             <param name="min">1</param>
             <param name="max">150</param>
             <message>age range: ${min} ~ ${max}</message>
         </field-validator>
     </field>
     
     <field name="birthday">
         <field-validator type="required">
             <message>birthday required</message>
         </field-validator>
         <field-validator type="date">
             <param name="min">2009-01-01</param>
             <param name="max">2009-12-31</param>
             <message>birthday range: ${min} ~ ${max}</message>
         </field-validator>
     </field>
     
     <field name="email">
         <field-validator type="email">
             <message>invalid email address</message>
         </field-validator>
     </field>
 </validators>

說明:
a.校驗框架有兩種校驗方式:field和validator。
field校驗:先指定需要校驗的屬性,再指定校驗方式。validator校驗:先指定校驗方式,再指定需要校驗的屬性。兩種方式是等價的。

field校驗:
<field name="name">
    <field-validator type="requiredstring" >
        <param name="trim">true</param>
        <message>name required</message>
    </field-validator>
    <field-validator type="stringlength">
        <param name="trim">true</param>
        <param name="minLength">6</param>
        <param name="maxLength">10</param>
        <message>name length range : ${minLength} ~ ${maxLength}</message>
    </field-validator>
</field>

validator校驗:
<validator type="requiredstring">
    <param name="fieldName">name</param>
    <param name="trim">true</param>
    <message>name required</message>
</validator>
<validator type="stringlength">
    <param name="fieldName">name</param>
    <param name="trim">true</param>
    <param name="minLength">6</param>
    <param name="maxLength">10</param>
    <message>name length range : ${minLength} ~ ${maxLength}</message>
</validator>

b.<field-validator type="requiredstring" >中的type及其對應的xwork類可以在xwork-2.1.2.jar/com.opensymphony.xwork2.validator.validators/default.xml中查找到。
default.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
        "-//OpenSymphony Group//XWork Validator Config 1.0//EN"
        "http://www.opensymphony.com/xwork/xwork-validator-config-1.0.dtd">

<!-- 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="long" class="com.opensymphony.xwork2.validator.validators.LongRangeFieldValidator"/>
    <validator name="short" class="com.opensymphony.xwork2.validator.validators.ShortRangeFieldValidator"/>
    <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"/>
    <validator name="conditionalvisitor" class="com.opensymphony.xwork2.validator.validators.ConditionalVisitorFieldValidator"/>
</validators>
<!--  END SNIPPET: validators-default -->

c. 對于校驗<field-validator type="requiredstring" >:String用requiredstring,其它類型用required。
d. 驗證錯誤將默認產生FieldError。
e. short-circuit="true" : 一個校驗失敗,是否是繼續(xù)執(zhí)行后續(xù)校驗。
f. 對于相同屬性的FieldError,validate()方法中的驗證和RegisterAction-validation.xml中的驗證都會執(zhí)行,并且FieldError都會顯示。
執(zhí)行順序: RegisterAction-validation.xml => validate()。


2、特定于業(yè)務邏輯的局部校驗:
對于struts.xml中<action>的method="register"指定的業(yè)務方法register(),使用校驗RegisterAction-register-validation.xml(與RegisterAction.java在同一目錄下)。同時,RegisterAction-validation.xml會被執(zhí)行。執(zhí)行順序:  RegisterAction-validation.xml => RegisterAction-register-validation.xml

3、Struts2客戶端校驗
    設置struts標簽<s:form>中validate="true"。這樣就會根據RegisterAction-validation.xml生成頁面Javascript,在客戶端執(zhí)行校驗。
 
 注意:
 a.struts標簽不能使用simple主題
 b.Struts2客戶端校驗功能較弱,一般不用。

4、FieldError和ActionError的實現
a.真正存放field級別錯誤信息的對象是LinkedHashMap。
b.該LinkedHashMap的key是String類型的,value是ArrayList類型,所以同一個key可以對應多個錯誤消息。
c.對于Action級別的錯誤信息,實際上是放置在ArrayList中的。
    
[參考資料]:
    《浪曦視頻之Struts2應用開發(fā)系列》