Validator驗證框架

 

Validator驗證框架 javascript

1、Validator框架的優點

       Validator框架是一個Struts插件,最初由David Winterfeldt設計並實現。Validator框架從Struts 0.5時代就可使用,但那時Validator框架只是被捐助的一個jar包。Apache組織爲了使開發人員更方便地使用Validator框架,決定從Struts1.1開始,將Validator框架做爲Struts的一部分同Struts一塊兒發佈。 html

Validator框架能夠在XML文件中配置驗證規則和驗證對象。所以,使用Validator框架能夠無需在ActionForm的子類中覆蓋validate方法就能夠很方便地驗證客戶端的提交數據。因爲Validator框架內置了不少預約義的驗證機制,如驗證某個屬性是否存在,驗證EMail是否合法等。因此在通常狀況下,只須要配置XML文件就能夠知足咱們的驗證需求。 java

在使用Validator框架時,就會發現這種方式要比直接使用validate方法進行驗證會給咱們帶來以下的好處: web

1.  更容易維護。 因爲驗證信息能夠被放置在同一個配置文件中,所以,咱們能夠更容易地來維護這些驗證信息。 正則表達式

2.  標準化。因爲不少簡單的驗證都是相同的。如用戶名和密碼都要求由字母、數字以及下劃下組成。若是將這些驗證都寫在validate方法中,對這些驗證進行標準化很是困難。而在Validator框架中的這些驗證機制都是預先定義的,所以,標準化相同的驗證對於Validator框架來講將是一件很是輕鬆的事。 sql

3.  避免重造輪子。雖然一些驗證很簡單,但若是想正確實現它們也是很是困難的。一個典型的例子是驗證EMail地址的格式。若是這個驗證要想天衣無縫,就必須按着RFC-2822規範的要求來驗證EMail地址。而若是咱們使用Validator框架,就無需再重造輪子來驗證EMail地址了。 shell

4.  減小重複代碼的數量。因爲Validator框 架提供了不少預約義的驗證,所以,咱們能夠避免本身寫不少重複的代碼進行驗證。固然,咱們也能夠將大量使用的驗證封裝在類的方法中,這些雖然能夠避免大量的重複勞動,但這就意味着咱們團隊的新成員要使用這些被封裝的驗證方法以前必須先學習它們。而最糟糕的狀況是不少開發人員可能會忘記使用這些由其餘成員實 現的驗證庫,而本身從新編寫具備一樣功能的驗證庫。固然,這一切若是使用Validator框架就均可以獲得解決。 apache

    5.  客戶端和服務端驗證自動切換。咱們只須要簡單地在JSP頁面中放一個單獨的<html::javascript/>元素就能夠將服務端的驗證轉換爲客戶端驗證(基於JavaScript的驗證)
   
雖然Validator框架的預約義驗證已經能夠知足大多數的驗證需求了,但在某些特殊狀況下,這些預約義驗證就沒法知足咱們的需求了,爲此,Validator框架也爲開發人員提供了擴展驗證機制的功能。這也使得Validator框架能夠完成更復雜的驗證工做。

數組

2、配置和使用Validator框架 瀏覽器

 1.  安裝Validator框架

    因爲ValidatorStruts的一個插件,所以,就須要在struts-config.xml文件中按着Struts插件的方式來安裝Validator框架。打開struts-config.xml文件,在<struts-config>元素中加入一個<plug-in>子元素,以下面的代碼所示:

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validator.xml" />
</plug-in>     

其中<set-property>元素設置了插件中使用的pathnames屬性的值。在pathnames屬性值中包含了兩個xml文件。

1validator-rules.xml:在這個文件中聲明瞭Validator框架的預約義驗證。這個文件能夠在Struts的發行包的lib目錄中能夠找到這個文件。在使用MyEclipseWeb工程添加Struts功能後,會自動將這個文件加到WEB-INF目錄中。

2validator.xml:這個文件定義了要驗證的對象。實際上,在這個文件中,包含了一個或多個ActionForm的子類及其要驗證的屬性和驗證規則。所以,這個文件就至關於validate方法。在Validator框架中,能夠有多個定義驗證對象的xml文件(能夠將不一樣的ActionForm的子類分散到不一樣的xml文件中),中間用逗號(,)隔開,以下面的代碼所示:

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validator1.xml,
                                             /WEB-INF/validator2.xml, /WEB-INF/validator3.xml"
 />
</plug-in>     

2.  使用Validator框架的一個例子

   
在本節將舉一個例子來演示如何使用Validator框架來驗證數據。咱們須要按着以下的六步來完成這個例子:

【第1步】創建FirstValidatorForm類(ValidatorForm的子類)

<samples工程目錄>\src\actionform目錄中創建一個FirstValidatorForm.java文件,代碼以下:

  package actionform;
  
import org.apache.struts.validator.ValidatorForm;
  
public class FirstValidatorForm extends ValidatorForm  // 必須從ValidatorForm繼承
  {
      
private String name;
      
private String age;
      
private String email;
      
public String getName()
      {
          
return name;
      }
      
public void setName(String name)
      {
          
this.name = name;
      }
      
public String getEmail()
      {
          
return email;
      }
      
public void setEmail(String email)
      {
          
this.email = email;
      }
      
public String getAge()
      {
          
return age;
      }
      
public void setAge(String age)
      {
          
this.age = age;
      }
  }

    要注意的是,要想使用Validator框架驗證數據,Form類就必須從ValidatorForm繼承,而不能從ActionForm繼承。這是由於ValidatorForm類是從ActionForm繼承的,在ValidatorForm類中已經覆蓋了validate方法來自動進行驗證工做,所以,咱們在ValidatorForm的子類中就不用寫validate方法了。

【第2步】創建ValidatorAction類(Action的子類)
   
<samples工程目錄>\src\action目錄中創建一個ValidatorAction.java文件,代碼以下:

  package action;
  
import javax.servlet.http.*;
  
import org.apache.struts.action.*;
  
public class ValidatorAction extends Action
  {
      
public ActionForward execute(ActionMapping mapping, ActionForm form,
              HttpServletRequest request, HttpServletResponse response)
      {
          response.setCharacterEncoding("GBK");
          
try
          {
              response.getWriter().println("
驗證成功!");
          }
          
catch (Exception e)
          {
          }
          
return null;
      }
  }

        ValidatorAction類是一個空的Struts動做類(除了輸出一行「驗證成功!」字符串)。這個動做是爲了正常運行含有Struts元素的JSP程序所編寫的。在之後的代碼中會常用到這個Struts動做類。

【第3步】配置struts-config.xml文件

    配置FirstValidatorFormValidatorAction的代碼以下所示

<form-bean name="firstValidatorForm" type=" actionform.FirstValidatorForm" />
<action name="firstValidatorForm" path="/firstValidator" scope="request" type=" action.ValidatorAction"  input="/firstValidator.jsp"/>       

其中firstValidator.jsp是用戶錄入信息的界面,也是顯示錯誤信息的界面。

【第4步】創建firstValidator.jsp
   
Web根目錄創建一個firstValidator.jsp文件,代碼以下:

  <%@ page pageEncoding="GBK"%>
  
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
  
<html>
    
<head>
      
<title>第一個Validator程序</title>
    
</head>
    
<body>
      
<html:form action="firstValidator" >
         
  名:
<html:text property="name" />&nbsp;&nbsp;<font color="red"><html:errors property="name"/></font><p>
         
  齡:
<html:text property="age"/>&nbsp;&nbsp;<font color="red"><html:errors property="age"/></font><p>
       EMail

<html:text property="email"/>&nbsp;&nbsp;<font color="red"><html:errors property="email"/></font><p>
              
<html:submit value="提交"/>
      
</html:form>  
    
</body>
  
</html>

    firstValidator.jsp中能夠看出,無論是否使用Validator框架進和驗證,對於JSP代碼來講是徹底同樣的。仍然是使用<html:errors>元素來顯示錯誤信息。但要注意,在使用Validator框架時,<html:errors>標籤的property屬性的值就是所對應ValidatorForm的子類的屬性名。

【第5步】配置validator.xml文件
   
在本例中只使用了一個XML文件(validator.xml)來配置要驗證的對象。validator.xml的代碼以下:

  <?xml version="1.0" encoding="GBK" ?>
  
<!DOCTYPE form-validation PUBLIC
   "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
            "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd"
>
  
<form-validation>
      
<formset>
          
<form name="firstValidatorForm">
              
<field property="name" depends="required,maxlength,minlength,mask">
                  
<msg name="required" key="error.name.blank" />
                  
<msg name="minlength" key="error.name.minLength" />
                  
<msg name="maxlength" key="error.name.maxLength" />
                  
<msg name="mask" key="error.name.alphanum" />
  
                  
<arg name="minlength" key="${var:minlength}" position="0" resource="false" />
                  
<arg name="maxlength" key="${var:maxlength}" position="0" resource="false" />
                  
<var>
                      
<var-name>minlength</var-name>
                      
<var-value>5</var-value>
                  
</var>
                  
<var>
                      
<var-name>maxlength</var-name>
                      
<var-value>10</var-value>
                  
</var>
                  
<var>
                      
<var-name>mask</var-name>
                      
<var-value>^[a-zA-Z0-9]*$</var-value>
                  
</var>
              
</field>
              
<field property="age" depends="required,integer,intRange">
                  
<msg name="required" key="error.age.blank" />
                  
<msg name="integer" key="error.age.integer" />
                  
<msg name="intRange" key="error.age.intRange" />
  
                  
<arg name="intRange" key="${var:min}" position="0" resource="false" />
                  
<arg name="intRange" key="${var:max}" position="1" resource="false" />
                  
<var>
                      
<var-name>min</var-name>
                      
<var-value>18</var-value>
                  
</var>
                  
<var>
                      
<var-name>max</var-name>
                      
<var-value>60</var-value>
                  
</var>  
              
</field>
              
<field property="email" depends="required,email">
                  
<msg name="required" key="error.email.blank" />
                  
<msg name="email" key="error.email.invalid" />
              
</field>
          
</form>
      
</formset>
  
</form-validation>

        validator.xml文件中的全部配置都放到<form-validation>元素中。在<form-validation>元素中有一個<formset>子元素,這個元素能夠定義多個<Form>元素,這個元素用來定義要驗證的ValidatorForm類的子類。其中name屬性值就是<form-bean>元素中的name屬性值。

<field>元素用來定義某個屬性的約束條件,如第一個<field>元素定義了name屬性必須存在(required)、必需要知足最小長度(minlength)和最大長度(maxlength)以及還要經過mask所指的正則表達式的驗證。

<msg>元素用來定義出錯信息在屬性文件中的Key(全部的出錯信息都在屬性文件中)。<arg>元素用來向出錯信息中的參數傳遞參數值。<var>元素用來定義變量名和變量值。

詳解:

 

<!--
     驗證規則配置文件的DTD,版本 1.1.3
     容許你開始處的DOCTYPE元素以後(固然DOCTYPE元素要在"xml"聲明以後),
     使用XML來配置你的驗證文件:
     <!DOCTYPE form-validation PUBLIC
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
      " http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
     $Id: validator_1_1_3.dtd,v 1.1.2.2 2004/04/06 22:20:36 rleland Exp $
-->
 
<!--
      "form-validation" 元素是配置文件結構的根元素,
      而且包含了全部其餘內嵌配元素及其配置。
-->
<!ELEMENT form-validation (global*, formset*)>

<!--
     在"global"元素中定義的元素都是全局的。能夠在文件
     其餘地方被引用
-->
<!ELEMENT global (validator*, constant*)>

<!--
      "validator"元素用來定義驗證器,這些驗證器能夠被在formset元素中
      field元素所引用。
      元素:
        validator          定義一個新的驗證器
        javascript         在客戶端驗證使用的javascript源代碼
      屬性:
          name             驗證(器)的名稱
          classname        處理服務器端驗證的類的類名
          method           服務器端處理驗證的方法名
          methodParams     要傳遞到服務器端驗證方法的參數,多個參數用逗號分開
          msg              驗證失敗時在消息資源中綁定的消息資源key。
                          若是不但願使用默認的key,能夠重寫它的值以指向所需的消息資源。
          depends          在調用證以前所須要調用的其餘驗證的列表,多個用逗號分隔。
                          若是想要進行當前驗證,那麼列表中的全部驗證必須成功。
          jsFunctionName   返回某一類型全部字段的JavaScript函數的函數名。
          jsFunction       被傳遞到對錶單進行表單驗證的JavaScript函數的函數名。
-->
<!ELEMENT validator (javascript?)>
<!ATTLIST validator name CDATA #REQUIRED>
<!ATTLIST validator classname CDATA #REQUIRED>
<!ATTLIST validator method CDATA #REQUIRED>
<!ATTLIST validator methodParams CDATA #REQUIRED>
<!ATTLIST validator msg CDATA #REQUIRED>
<!ATTLIST validator depends CDATA #IMPLIED>
<!ATTLIST validator jsFunctionName CDATA #IMPLIED>
<!ATTLIST validator jsFunction CDATA #IMPLIED>

<!--
      "javascript"元素定義了客戶端執行驗證的JavaScript函數.
-->
<!ELEMENT javascript (#PCDATA)>

<!--
      "constant"元素定義了能夠在"field"元素中替代參數的靜態常量值。
      "constant-name"和"constant-value"元素定義了常量引用id和替代值。
-->
<!ELEMENT constant (constant-name, constant-value)>
<!ELEMENT constant-name   (#PCDATA)>
<!ELEMENT constant-value (#PCDATA)>

<!--
       "formset"定義了一個本地表單集合。若是對於指定的地區(國際化用),那麼就只能重寫
       相應字段的驗證。由於本地化是隨地區而定的,因此若是須要本地化,就要改動language或
       country屬性或者二者都改。
-->
<!ELEMENT formset (constant*, form+)>
<!ATTLIST formset language CDATA #IMPLIED>
<!ATTLIST formset country CDATA #IMPLIED>
<!ATTLIST formset variant CDATA #IMPLIED>

<!--
      "form"元素定義了一個須要驗證的字段集。name屬性與web應用中表單
      的相應字段名相同。
-->
<!ELEMENT form (field+)>
<!ATTLIST form name CDATA #REQUIRED>

<!--
      "field"元素定義了須要驗證的屬性。在一個web應用中,一個字段會對應
      一個在HTML表單中的空間。爲了驗證這些屬性,驗證器以JavaBean的方式
      工做。field元素接受以下
      屬性:
      property         對應於此field元素的JavaBean(一般爲ActionForm)中須要驗證的屬性。
      depends          在調用證以前所須要調用的其餘驗證的列表,多個用逗號分隔。
                      若是想要進行當前驗證,那麼列表中的全部驗證必須成功。
      page             與當前表單相應的JavaBean(一般爲ActionForm)可能包含一個
                      page屬性。只有字段中的"page"屬性值等於或者小於表單中的
                      值時框架纔會處理JavaBean。若是是使用帶有"wizard"(嚮導)
                      來完成一個大型表單的話,這個屬性會很是有用,由於它能夠
                      防止某些頁面被無心中跳過。
       [0]——默認值。
      indexedListProperty
                      "indexedListProperty"便可以返回一個數組或者Collection類
                      方法名。能夠經過此方法獲得一個列表而後經過這個列表的循環訪問
                      ,執行對字段的驗證。
-->
<!ELEMENT field (msg|arg|arg0|arg1|arg2|arg3|var)*>
<!ATTLIST field property CDATA #REQUIRED>
<!ATTLIST field depends CDATA #IMPLIED>
<!ATTLIST field page CDATA #IMPLIED>
<!ATTLIST field indexedListProperty CDATA #IMPLIED>

<!--
      "msg"元素定義了一個自定義消息key,當驗證字段失敗時,使用此消息key。
      噹噹前的字段驗證失敗且msg元素沒有指定值時,每一個驗證器都會使用自身
      默認的消息屬性。應用到字段的每一個驗證器能夠有本身的msg元素。
      msg元素接受以下的屬性
       name         指定對應此msg元素的驗證器(驗證規則)的名稱。
     
       bundle       指明包含key屬性所指名稱的消息資源綁定。
       key          消息資源綁定中返回消息模版的key。
       resource     若是設置爲"false", 表示直接在key屬性中設置文本。若是爲
             "true"則使用消息資源綁定中的值。
                   [true]——默認值。
-->
<!ELEMENT msg EMPTY>
<!ATTLIST msg key CDATA #REQUIRED>
<!ATTLIST msg name CDATA #REQUIRED>
<!ATTLIST msg bundle CDATA #IMPLIED>
<!ATTLIST msg resource CDATA #IMPLIED>
 
<!--
      "arg"元素爲使用它的驗證器或者field定義了消息替換模版。
      arg元素接受以下屬性。
       name         與msg元素對應的驗證器的名稱。
             若是沒有指定這個屬性,則適用於全部的驗證規則,
             並取代position中指定的位置的參數。
           
       bundle       指明包含key屬性所指名稱的消息資源綁定。
       key          消息資源綁定中返回消息模版的key。
       resource     若是設置爲"false", 表示直接在key屬性中設置文本。若是爲
             "true"則使用消息資源綁定中的值。
                   [true]——默認值。
                 
       position     在消息中替換參數的未知。
             例如,position="0"就是第一個參數。
             [0]——默認值
-->
<!ELEMENT arg EMPTY>
<!ATTLIST arg key CDATA #REQUIRED>
<!ATTLIST arg bundle CDATA #IMPLIED>
<!ATTLIST arg name CDATA #IMPLIED>
<!ATTLIST arg resource CDATA #IMPLIED>
<!ATTLIST arg position CDATA #IMPLIED>
 
<!--
  「特別不建議」經過使用<arg position="0"/>來替代arg0元素!
      "arg0"元素爲使用它的驗證器或者field定義了消息替換模版中的第一個
      替換參數的值。
      arg0元素接受如下屬性。
       name         與msg元素對應的驗證器的名稱。
     
       key          消息資源綁定中返回消息模版的key。
       resource     若是設置爲"false", 表示直接在key屬性中設置文本。若是爲
             "true"則使用消息資源綁定中的值。
                   [true]——默認值。
-->
<!ELEMENT arg0 EMPTY>
<!ATTLIST arg0 name CDATA #IMPLIED>
<!ATTLIST arg0 key CDATA #IMPLIED>
<!ATTLIST arg0 resource CDATA #IMPLIED>

<!--
  「特別不建議」經過使用<arg position="1"/>來替代arg1元素!
      "arg1"元素爲使用它的驗證器或者field定義了消息替換模版中的第二個
      替換參數的值。
      arg1元素接受如下屬性。
       name         與msg元素對應的驗證器的名稱。
     
       key          消息資源綁定中返回消息模版的key。
       resource     若是設置爲"false", 表示直接在key屬性中設置文本。若是爲
             "true"則使用消息資源綁定中的值。
                   [true]——默認值。
-->
<!ELEMENT arg1 EMPTY>
<!ATTLIST arg1 name CDATA #IMPLIED>
<!ATTLIST arg1 key CDATA #IMPLIED>
<!ATTLIST arg1 resource CDATA #IMPLIED>

<!--
  「特別不建議」經過使用<arg position="2"/>來替代arg2元素!
      "arg2"元素爲使用它的驗證器或者field定義了消息替換模版中的第三個
      替換參數的值。
      arg2元素接受如下屬性。
       name         與msg元素對應的驗證器的名稱。
     
       key          消息資源綁定中返回消息模版的key。
       resource     若是設置爲"false", 表示直接在key屬性中設置文本。若是爲
             "true"則使用消息資源綁定中的值。
                   [true]——默認值。
-->
<!ELEMENT arg2 EMPTY>
<!ATTLIST arg2 name CDATA #IMPLIED>
<!ATTLIST arg2 key CDATA #IMPLIED>
<!ATTLIST arg2 resource CDATA #IMPLIED>

<!--
  「特別不建議」經過使用<arg position="3"/>來替代arg3元素!
      "arg3"元素爲使用它的驗證器或者field定義了消息替換模版中的第四個
      替換參數的值。
      arg3元素接受如下屬性。
       name         與msg元素對應的驗證器的名稱。
     
       key          消息資源綁定中返回消息模版的key。
       resource     若是設置爲"false", 表示直接在key屬性中設置文本。若是爲
             "true"則使用消息資源綁定中的值。
                   [true]——默認值。
-->
<!ELEMENT arg3 EMPTY>
<!ATTLIST arg3 name CDATA #IMPLIED>
<!ATTLIST arg3 key CDATA #IMPLIED>
<!ATTLIST arg3 resource CDATA #IMPLIED>

<!--
      "var"元素設置一個參數,使得field元素把它傳遞給相應的驗證器,
      例如,在一個最小或者最大值的範圍驗證中的值。這些參數一樣也可
      被一個arg?所引用,可是必須經過使用shell語法:${var:var-name}
      才行。
-->
<!ELEMENT var (var-name, var-value, var-jstype?)>
 
<!--
      須要提交給字段驗證器的變量的名稱。
-->
<!ELEMENT var-name   (#PCDATA)>
 
<!--
      須要提交給字段驗證器的變量的值。
-->
<!ELEMENT var-value (#PCDATA)>
<!--
      JavaScript類型,可選值 [int| string | regexp]
-->
<!ELEMENT var-jstype (#PCDATA)>

 

 

【第6步】ErrorDescription.properties文件中添加錯誤信息

   
打開ErrorDescription.properties文件,在文件的後面添加以下的內容:

  error.name.blank = 姓名不能爲空
  error.name.minLength = 
姓名的長度不能小於{0}
  error.name.maxLength = 
姓名的長度不能大於{0}
  error.name.alphanum = 
姓名必須由字母和數字組成
  error.age.blank = 
年齡不能爲空
  error.age.integer = 
年齡必須爲數字
  error.age.intRange = 
年齡必須在{0}{1}之間

  啓動Tomcat,在IE中輸入以下的URL來測試程序:

   
http://localhost:8080/samples/%20firstValidator.jsp

   
在輸入一些錯誤信息後,點擊「提交」按鈕,將出現相似下圖的效果。

將會按着depends屬性中的約束來驗證items屬性的每個值。咱們還能夠將propertyindexedListProperty配合使用,以下面代碼所示:

  <field indexedListProperty="items"  property="employee.age"  depends=>  </field>

    Validator框架將根據上述的配置代碼來驗證items屬性中的每一項的employee.age屬性。

2、使用常量和變量

1. 常量

   
Struts1.x系列教程(10):Validator驗證框架入門》一文中的name屬性使用了mask進行驗證。這個mask實際上表明瞭一個正則表達式。但若是在validator.xml文件中有不少個地方須要用到這個正則表達式,那就它就會在不少地方重複。爲此,咱們可使用常量來避免這種事情發生。   

常量分爲全局常量和局部常量。

1)全局常量

全局常量能夠被用在validator.xml中定義的全部form中。咱們可使用<global>元素來配置全局常量。爲了配置全局常量,將以下的內容放到第一個<formset>元素的前面。

  <global>
      
<constant>
          
<constant-name>mask</constant-name>
          
<constant-value> ^[a-zA-Z0-9]*$ </constant-value>
      
</constant>
  
</global>
  
<formset>

2)局部常量
   
局部常量須要放到<formset>元素的開始位置(根據DTD的定義,局部常量只能放到這裏,而全局常量能夠放在第一個<formset>元素的前面,也能夠放到<formset>的後面)。以下面的代碼所示:

  <formset>
      
<constant>
          
<constant-name>mask</constant-name>
          
<constant-value> ^[a-zA-Z0-9]*$ </constant-value>
      
</constant>
      
<form name="firstValidatorForm"> 
       
  
</formset>

 咱們能夠編寫以下的代碼來使用mask常量:

<var>
    <var-name>mask</var-name>
    <var-value> ${mask}</var-value>
</var>


2. 變量
    Validator
框架經過<var>元素來定義變量。變量將做爲<field>的子元素被使用。主要向depends屬性值 (如mask)以及<msg>的錯誤信息傳遞數據。以下面的代碼經過變量required姓名傳遞給了錯誤信息的第一個參數{0}

<field property="name"  depends="required ">
    <msg name="required" key="error.name.blank" />
    <arg name="required" key="${var:required}" position="0" resource="false" />
    <var>
        <var-name>required</var-name>
       
<var-value>姓名</var-value>
   
</var>
</field>

3、客戶端驗證

 使用Validator框架的好處之一就是能夠很容易地將服務端驗證變爲客戶端驗證(JavaScript驗證)。爲了完成這一轉換,咱們只須要修改兩個地方。如今就拿Struts1.x系列教程(10):Validator驗證框架入門》中的firstValidator.jsp爲例來講明要修改什麼。
   
首先,在firstValidator.jsp中的任何地方(固然,任何地方指的是客戶端代碼區,並不包括<%...%><%--... --%>所包含的內容)添加以下的<html:javascript>標籤:

  <html:javascript formName="firstValidatorForm"/>

而後在<html:form>標籤中加入以下的屬性:

  onsubmit="return validateFirstValidatorForm(this);"

    如今再運行firstValidator.jsp,若是輸入錯誤,IE就會直接彈出錯誤信息對話框。咱們查看客戶端源代碼就會發現,在源代碼中多了不少JavaScript代碼。實際上,當加入<html:javascript>標籤後,在運行JSP頁面時,Servlet引擎就會將Validator框架中JavaScript版本的預約義驗證代碼連同HTML代碼都發送到客戶端。這些JavaScript代碼中有一個入口函數,這個函數的名稱前綴爲validate,後面是首字母大寫的Form名。在<html:form>標籤中的onsubmit事件中調用這個入口函數就能夠經過JavaScript代碼來驗證客戶端錄入的數據了。

下面列出了Validator框架的預約義驗證(Struts的版本號爲1.2.9)。

Validator

變量

引起條件

required

字段只有空格

validwhen

test

test條件失敗(詳見下一節)

minlength

minlength

字段的字符數小於minlength

maxlength

maxlength

字段的字符數大於maxlength

mask

mask

字段值不匹配mask所指的個正則表達式

byteshortintegerlongfloatdouble

字段值沒法轉換爲這些數據類型

date

datePattern

datePatternStrict

字值值不能按着指定的格式轉換爲日期類型

intRangefloatRangedoubleRange

minmax

字段值不在指定的範圍內

creditCard

字段值不是一個信譽卡號

email

字段值不是一個合法的email

url

allowallschemes

allow2slashes

nofragments

schemes

字段不是一個URL

關於Validator框架標準驗證的詳細信息,讀者能夠訪問以下的URL  

http://struts.apache.org/1.2.9/userGuide/dev_validator.html

    下面來舉一個validwhen驗證的例子。
    validwhen
能夠驗證當前屬性和其餘屬性的關係,如在驗證密碼時,要保證兩次輸入的密碼一致,驗證代碼以下:

<field property="password1" depends="validwhen">
    <msg name="validwhen" key="error.password1.confirmation" />
   
<var>
       
<var-name>test</var-name>
       
<var-value>
            (password1!= null) and (*this* == password)
       
</var-value>
   
</var>
</field>


   
使用validwhen也能夠驗證嵌套和索引屬性,以下面的代碼所示:

<field property="field1" depends="validwhen">
    <msg name="validwhen" key="error.field.message" />
   
<var>
       
<var-name>test</var-name>
       
<var-value>
            (*this* == field2.name) and (*this* != field3[1])
       
</var-value>
   
</var>
</field>

    其中*this*表示當前屬性的值。

====================================================================

1、動態Form簡介

    雖然ActionForm功能強大,但有些時候使用起來有些麻煩。如每創建一個用戶錄入界面(JSP頁面),就得創建一個ActionForm子類來和這個頁面對應。固然,咱們能夠採用嵌套屬性從必定程度上彌補這個問題。可是在創建新的用戶錄入界面時,仍不可避免地要創建新的ActionForm子類。

    Struts1.2.6及之後的Struts版本中提供了一種動態Form的技術。使得不用再創建新的ActionForm就能夠封裝用戶提交的數據。實際上,這種技術將定義ActionForm子類的工做變成了編寫XML文件的工做。

    每定義一個動態Form,就要在struts-config.xml中加一個<form-bean>元素,並使用<form-property>子元素來定義動態Form的屬性。

    在本章的最後還會介紹一個LazyValidatorForm類,經過這個類甚至能夠不定義動態Form的屬性就可使用動態Form。這將大大簡化開發人員的工做量。    

2、聲明動態Form 

    聲明一個動態Form很是簡單,只須要在struts- config.xml<form-beans>元素中加入一個<form-bean>子元素,並使用<form- property>元素來定義動態Form的屬性。咱們能夠定義的屬性類型有簡單屬性(如String)、索引屬性(如數組)、映射屬性(如 HashMap)以及嵌套屬性(屬性類型是另外一個類)。
   
對於動態Form來講,Form的類型必須是org.apache.struts.action.DynaActionForm或其子類。聲明一個動態Form的代碼以下:

<form-bean name="dynamicForm"  type="org.apache.struts.action.DynaActionForm">
    <!-- 聲明一個簡單屬性 -->
    <form-property name="simpleProp" type="java.lang.String" initial="bill"/>
    <!-- 聲明一個索引屬性 -->
    <form-property name="indexedProp" type="java.lang.String[]" />
    <!-- 聲明一個映射屬性 -->
    <form-property name="mappedProp" type="java.util.HashMap" />
    <!-- 聲明一個嵌套屬性 -->
    <form-property name="nestedProp" type="com.bean.MyBean" />
</form-bean>

3、動態Form的屬性類型

    下面列出了動態Form支持的簡單屬性的全部類型:

  • java.math.BigDecimal
  • java.math.BigInteger
  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Class
  • java.lang.Double
  • java.lang.Float
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Short
  • java.lang.String
  • java.sql.Date
  • java.sql.Time
  • java.sql.Timestamp 

實際上,上面的數據類型就是Java中提供了簡單數據類型。它們用在動態Form中和在Java中表明的數據類型是徹底同樣的。咱們還可使用<form-property>元素的initial屬性爲動態Form的簡單屬性指定一個默認值。如在例程6-11name屬性的默認值爲「bill」。

對於索引屬性的類型來講,能夠是數組,也能夠是java.util.List接口的類(如ArrayList)。咱們還能夠爲動態Form的屬性指定實現java.util.Map接口的類做爲數據類型(也就是映射屬性)。但遺憾的是,若是使用動態Form,就沒法使用泛型進行自動類型轉換了。

4、訪問動態Form

    咱們可使用DynaActionForm類的getter方法來讀取動態Form中的屬性值。DynaActionForm類的getter方法有三個重載形式,分別用來讀取簡單屬性、索引屬性和映射屬性。這三個getter方法的定義以下:

  public Object get(String name) ;   // 讀取簡單屬性
  public Object get(String name, int index) ;  // 讀取索引屬性
  public Object get(String name, String key);  // 讀取映射屬性

   
   
下面的代碼演示瞭如何經過getter方法得到動態Form的屬性值:

DynaActionForm dForm = (DynaActionForm)form;
String name = (String)dForm.get("name");
String[] hobbies = (String[])dForm.get(「hobbies」);
String value1 = (String)dForm.get(「myMap」, 「key1」);

    除了上述的get方法外,DynaActionForm還提供了getStringgetString方法,分別用來讀取StringString[]類型的屬性值,這兩個方法的定義以下:

public String getString(String name) ;  
public String[] getStrings(String name) ;

    下面的代碼演示瞭如何經過getStringgetStrings方法得到動態Form的屬性值:

String name = dForm.getString(「name」);  // 至關於String name = (String)dForm.get("name");
String[] hobbies = dForm.getStrings(「hobbies」);  // 至關於String[] hobbies = (String[])dForm.get(「hobbies」);

    在使用getStringgetStrings方法時應注意,這兩個方法只能讀取StringString[]類型的屬性,讀取其餘類型的屬性將會拋出異常。  

5、一個動態Form的例子

    咱們在這一部分來實現一個完整的動態Form的例子,在這個例子中的動態Form有四個屬性,三個是簡單數據類型,一個是數組類型。完成這個例子須要以下四步:

【第1步】配置動態Form
   
打開struts-config.xml,在<form-beans>元素中加入以下的內容:

<form-bean name="dynamicForm" type="org.apache.struts.action.DynaActionForm">
    <form-property name="name" type="java.lang.String" />
    <form-property name="age" type="java.lang.Short" />
    <form-property name="salary" type="java.lang.Float" />
    <form-property name="hobby" type="java.lang.String[]" />
</form-bean>

【第2步】編寫Struts Action
   
這個Struts Action類負責從動態Form中得到屬性值,並輸出到客戶端瀏覽器。在<samples工程目錄>"src"action目錄中創建一個DynamicAction.java文件,代碼以下:

  package chapter6.action;
  
  
import javax.servlet.http.*;
  
import org.apache.struts.action.*;
  
import java.io.*;
  
  
public class DynamicAction extends Action
  {
      
public ActionForward execute(ActionMapping mapping, ActionForm form,
              HttpServletRequest request, HttpServletResponse response)
      {
          
try
          {
              DynaActionForm dForm = (DynaActionForm) form;
              String name = (String) dForm.get("name");
              Short age = (Short) dForm.get("age");
              Float salary = (Float) dForm.get("salary");
              
// 得到數組類型字段值的數組長度
              int hobbyCount = ((String[]) dForm.get("hobby")).length;
              PrintWriter out = response.getWriter();
              out.println("name: " + name + "<p/>");
              out.println("age: " + age + "<p/>");
              out.println("salary: " + salary + "<p/>");
              
for (int i = 0; i < hobbyCount; i++)
                  out.println("hobby" + (i + 1) + ": " + dForm.get("hobby", i) + "<p/>");
          }
          
catch (Exception e)
          {
          }
          
return null;
      }
  }

【第3步】配置Struts Action     

    打開struts-config.xml文件,在<action-mappings>元素中加入以下的內容:

  <action name="dynamicForm" path="/dynamic" scope="request" type="action.DynamicAction" />


【第4步】編寫用戶錄入數據的JSP頁面

    Web根目錄中創建一個dynamic.jsp文件,代碼以下:

  <%@ page pageEncoding="GBK"%>
  <%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
  
<html>
    
<head>
      
<title>測試動態Form</title>
      
<html:base/>
    
</head>
    
<body> 
      
<html:form action="dynamic"  >
         
  名:<html:text property="name" />&nbsp;&nbsp;<p>
         
  齡:<html:text property="age" />&nbsp;&nbsp;<p>
         
  資:<html:text property="salary" />&nbsp;&nbsp;<p>
         
愛好1<html:text property="hobby"  value=""/>&nbsp;&nbsp;<p>
         
愛好2<html:text property="hobby" value=""/>&nbsp;&nbsp;<p>
         
愛好3<html:text property="hobby" value=""/>&nbsp;&nbsp;<p>
                
<html:submit value="提交" />
      
</html:form>  
    
</body> 
  
</html>


   
啓動Tomcat後,在IE中輸入以下的URL來測試程序:

http://localhost:8080/samples/dynamic.jsp

6、驗證動態Form

有兩種方法能夠驗證動態Form

1. DynaActionForm的子類中覆蓋validate方法。

2. 若是要使用Validator框架來驗證動態Form,須要用DynaActionForm的子類org.apache.struts.validator. DynaValidatorForm或其子類來做爲動態Form的類型。

在使用DynaValidatorForm的了類時,要想使用Validator框架的驗證機制,須要在DynaValidatorForm子類的validate方法的開始位置使用 super.validate()語句來調用DynaValidatorForm中的validate方法

相關文章
相關標籤/搜索