struts2-校驗框架

Struts2提供的客戶端校驗
儘管這種支持比較弱,但採用Struts2中的客戶端校驗時需要注意以下幾點
1..<s:form validate="true">的validate屬性設置爲TRUE
2..不能將<s:form theme="">的theme屬性設置爲simple
3..建議將<s:form/>的action和namespace屬性分開寫
4..可以在頁面中使用<s:head/>標籤來引入樣式
5..最好不要使用Struts2提供的客戶端校驗
設置validate="true"之前和之後的JSP頁面在運行時的源代碼是不同的
設置該屬性之前,表單的οnsubmit="return true;"
設置該屬性之後,表單的οnsubmit="return validateForm_register();"
並且在源碼中多出了一段函數名爲validateForm_register()的JavaScript代碼
這個函數的具體內容與ValidateFrameAction-validation.xml中設置的內容很相似
並且Struts2的客戶端驗證的提示信息都是顯示在表格中各個字段正上方的
這種顯示是很死板的,遠遠不如我們自己編寫JavaScript代碼來的強大
Struts2爲我們提供的客戶端校驗,在使用起來很不方便,故不推薦使用
所以儘管Struts2是很好的一個框架,但並不是說它的所有功能都是非常棒的
它所提供的客戶端校驗猶如雞肋一般,所以我們更多的還是自己編寫JavaScript代碼
在實際開發中,也幾乎不會使用到Struts2提供的客戶端校驗
使用的更多的還是它的服務端的校驗,這也是Strtus2的強項


Struts2提供的校驗框架
對於一個健壯的項目應用來說,僅僅提供一個客戶端校驗,是不安全的
因爲有些惡意的用戶可能會嘗試着不通過Web網頁的方式來訪問
可以通過遠程登錄的方式訪問某臺主機的某個資源,這時就完全脫離了瀏覽器,脫離了HTML
直接通過HTTP底層的協議來發送信息,此時就可以繞過輸入信息的頁面而直接向服務器發送請求
也就是說,服務器端的驗證,是整個請求的最後一道防線
而Struts2恰好爲我們提供了一個校驗框架,用於在服務端驗證前臺提交過來的表單
在Struts2中,它的每一個校驗框架都對應着每一個Action,而且它的命名是有限制的
比如相對於validateFrameAction而言,它的驗證框架就必須爲validateFrameAction-validation.xml
其中  -validation.xml 是固定不變的。然後在它前面加上Action名字之後,Struts2就可以識別了
並且校驗文件必須與它所對應的Action類處於同一目錄下
使用該驗證框架的兩個條件:1..使用validation攔截器,2..它所驗證的Action需要繼承ActionSupport類
並且當驗證失敗出現message時,它會轉向到INPUT頁面來顯示message消息


字段校驗和非字段校驗
所謂的字段校驗,即校驗ValidateFrameAction中的屬性。一個<field>表示對Action中的一個屬性的校驗
字段校驗,屬於是字段優先。即我去校驗誰,然後是我用誰去校驗
非字段校驗,則校驗器優先。即我用誰去校驗,然後是我去校驗誰
即字段校驗中先定義name="username"對哪個字段校驗,再定義type="requiredstring"如何校驗
而非字段校驗先定義type="requiredstring"確定校驗器,再定義name="fieldName"指定所校驗的屬性
字段校驗和非字段校驗的本質都是一樣的,只是說話的順序不同罷了。反映到底層後,二者實質上都是一樣的
相對來說不推薦使用非字段驗證,實際應用中如果需要驗證的字段非常多的話,那麼在維護的時候就比較困難了


深剖Struts2校驗框架的本質
展開xwork-2.0.4.jar中的com.opensymphony.xwork2.validator.validators包裏面發現有很多的校驗類
因此,我們知道,我們現在所使用的這種校驗框架,實際上就是由Struts2已經給我們提供好的一些類
這些類來校驗客戶端的表單的輸入請求,這些類,這些校驗,都是由Struts2已經內置好的了,我們可以直接使用
然後打開包裏面的default.xml文件,就可以知道<field-validator>中type是取值於default.xml文件的
expressionfieldexpression都是用於OGNL表達式的判斷,分別返回Action級別Field級別的錯誤
conversion用於格式轉換出現錯誤時的判斷。

stringlength判斷字符串長度。

regex用於正則表達式的判斷


對Action中某一方法的校驗
假設在validateFrameAction中存在test()方法,如果對test()方法進行校驗的話
那麼就可以提供一個類似於validateFrameAction-test-validation.xml的文件
但是,validateFrameAction-validation.xml仍會被校驗
也就是說,如果validateFrameAction-validation.xml和validateFrameAction-test-validation.xml共存的話
那麼Struts2會先校驗validateFrameAction-validation,然後再校驗validateFrameAction-test-validation
但前提是,配置<action/>時,所調用的不是execute()方法,而是method="test",即調用的Action中的是test()方法
所以,假如一個Action中存在多個處理邏輯,那麼就不要再提供validateFrameAction-validation.xml全局校驗
而是建議爲具體的每一個方法提供對應的類似於validateFrameAction-test-validation.xml的局部的校驗文件


校驗文件與Action中的validate()共存時
如果在提供了校驗文件的同時,也重寫了Action中的validate()方法那麼二者都會執行
當校驗的信息不是特別複雜的時候,推薦儘量使用校驗文件的方式
當校驗的信息特別特別複雜的時候,可以使用validate()方法,即硬編碼的方式進行校驗
如果validateFrameAction-validation.xml與validateFrameAction中的validate()共存的話
那麼執行順序是:校驗文件先執行validate()後執行。假設二者都對username進行了校驗設置
那麼後執行的validate()並不會沖刷掉先執行的校驗文件中設置的信息,二者都會輸出
由於先執行校驗文件,所以首先顯示的是校驗文件中的錯誤提示信息,後顯示validate()的信息
另外,我們可以在Debug模式下運行項目,然後判斷出校驗文件和validate()的執行順序
首先在validationAwareSupport類的addFieldError()方法中設置斷點
然後以Debug模式運行,通過按F6在Debug中的Variables視圖裏觀察errorMessage顯示的信息的先後來判斷
最後得到的結果就是校驗文件先執行,而validate()方法是後執行的
而Struts2會先將校驗文件中<message/>放到與username的Key對應Value的ArrayList中,即增加一行錯誤消息
當Action中的validate()方法中的this.addFieldError("username","aaaaaaaaaaa")執行時
它就會將aaaaaaaaaaa直接放到Key爲userame所對應的ArrayList
因此當執行完validate()中的this.addFieldError()方法時,內存中的情況是這樣的
一個username作爲一個Key,它的Value是一個ArrayList,而此時的ArrayList裏面包含了兩個元素
第一個元素是校驗文件裏面<message/>中的信息第二個元素就是aaaaaaaaaaa
由於在頁面中採用的是Struts2的標籤庫,所以,它會將ArrayList中的信息全部都迭代取出來
因此在頁面中就會先顯示校驗文件中的<message/>信息,然後顯示addFieldError()所設定的錯誤信息

備註:這裏所說的東西,如果看不明白的話,可以先看看下面的剖析addFieldError()方法


子類Action中的方法的校驗細節
甚至還存在一種特殊的情況,比如ParentAction{test}ChildAction extends ParentAction{test}
如果同時提供了ParentAction-validation.xml和ParentAction-test-validation.xml文件的話
並且對應子類也提供了ChildAction-validation.xml和ChildAction-test-validation.xml文件
我們想對子類中的test()方法進行校驗,那麼它的執行流程如下
先執行ParentAction-validation.xml文件再執行ParentAction-test-validation.xml文件
再執行ChildAction-validation.xml文件最後執行ChildAction-test-validation.xml文件
就好似類的繼承,在New子類的一個實例的時候,會先New出父類的對象,然後才New出子類的對象
先有父親,再有孩子嘛。校驗也是這樣的。但是我們不推薦將Action定義成這樣
僅僅是對子類的test()方法進行校驗,竟然需要調用四個校驗文件,很不合理
就這種情況而言,輕易不會發生,僅供瞭解


Struts2中的兩種類型的錯誤信息
在Struts2中,提示的錯誤信息有兩種,一種是Field級別的一種是Action級別的
將錯誤信息放到ActionError的過程中,實際上是把錯誤信息放到Arraylist()中了
將錯誤信息放到FieldError的過程中,實際上是把錯誤信息放到Map()中了
這個Map的key就是屬性的名字,它的value就是增加的錯誤消息
當FileError或者ActionError中包含錯誤信息時,Struts2就會認爲類型轉換是錯誤的
然後就會轉向到INPUT頁面,而不會執行execute()方法
如果在Action中將某一個出錯信息放到了addFieldError()裏面的話
那麼就可以在JSP頁面中使用<s:fielderror/>標籤將FieldError中的信息輸出
另外,儘管Struts2內置了錯誤信息顯示的功能,但是它也只能顯示FileError中的錯誤信息
但我們可以通過手工添加<s:actionerror/>標籤在頁面中顯示ActionError裏的錯誤信息


剖析addFieldError()方法

  1. //通過查看父類ActionSupport.java的源碼,查找到了該方法的原形,代碼如下  
  2. public void addFieldError(String fieldName,String errorMessage){  
  3.     validationAware.addFieldError(fieldName,errorMessage);  
  4. }  
  5. //fieldName代表屬性的名字,errorMessage代表錯誤的消息  
  6. //validationAware是一個validationAwareSupport類型的一個實例  
  7. //validationAwareSupport類實現了validationAware和Serializable接口  
  8. //validationAwareSupport類中的addFieldError()方法的代碼如下所示  
  9. public synchronized void addFieldError(String fieldName,String errorMessage){  
  10.     final Map errors = internalGetFieldErrors();  
  11.     List thisFieldErrors = (List) errors.get(fieldName);  
  12.     if (thisFielsErrors == null){  
  13.         thisFielsErrors = new ArrayList();  
  14.         errors.put(fieldName, thisFielsErrors);  
  15.     }  
  16.     thisFielsErrors.add(errorMessage);  
  17. }  
  18. //這是非常非常重要的方法,通過它的代碼就足以顯示出FieldError中的Map裏面到底是什麼東西  
  19. //而internalGetFieldErrors方法也是在validationAwareSupport類中定義的,它的代碼如下  
  20. private Map internalGetFieldErrors(){  
  21.     if (fieldErrors == null){  
  22.         fieldErrors = new LinkedHashMap();  
  23.     }  
  24.     return fieldErrors;  
  25. }  
這裏的fieldErrorsvalidationAwareSupport類定義的私有的Map類型的成員變量
LinkedHashMap是Map的一個具體的實現,它使用列表的方式來實現的
也就是說,首先判斷fieldErrors是否爲空。起初fieldErrors肯定爲空
那麼既然它是空的,那麼就實例一個LinkedHashMap對象,賦給fieldErrors並返回它
接着在addFieldError()方法中用final的Map類型的errors接收LinkedHashMap類型的fieldErrors
所以說真正存放Field級別錯誤信息的對象是LinkedHashMap
然後通過List thisFieldErrors = (List) errors.get(fieldName);代碼可以發現
它是使用LinkedHashMap類型的errors.get()一個String類型的Key,然後將返回的Value值再轉換成List類型
因此我們可以很明確的大膽的說出來:對於LinkedHashMap,它的key是一個String,它的value是一個List
接下來執行if()語句。如果它得到的value值是null,那麼它就會New一個ArrayList()
換句話說,這個List類型的value是用一個ArrayList()來實現的
所以說該LinkedHashMap的key是String類型的,value是ArrayList類型的
由於它的value是ArrayList類型的,所以它的一個key所對應的value裏面就可以存放多個值
只要調用了validationAwareSupport類中的addFieldError()方法的話,就說明已經有一個錯誤發生了
那麼它首先會針對於fieldName的名字,找到它對應的value
如果value爲空,說明與fieldName所對應的value根本就不存在
也就是說LinkedHashMap中並沒有這一行映射,因此它就直接給我們New出來一個新的ArrayList
然後將fieldName和剛剛生成好的ArrrayList放置到LinkedHashMap中
此時的LinkedHashMap中的Key就是表單裏的輸入域的name值,Value是一個空的ArrayList
然後再執行thisFielsErrors.add(errorMessage);也就是在ArrayList中增加一條錯誤信息


剖析addActionError()方法

  1. //通過查看父類ActionSupport.java的源碼,查找到了該方法的原形,代碼如下  
  2. public void addActionError(String anErrorMessage){  
  3.     validationAware.addActionError(anErrorMessage);  
  4. }  
  5. //而validationAwareSupport類中的addActionError()方法的代碼如下所示  
  6. public synchronized void addActionError(String anErrorMessage){  
  7.     internalGetActionErrors.add(anErrorMessage);  
  8. }  
  9. //而internalGetActionErrors方法也是在validationAwareSupport類中定義的,它的代碼如下  
  10. private Collection internalGetActionErrors(){  
  11.     if (actionErrors == null){  
  12.         actionErrors = new ArrayList();  
  13.     }  
  14.     return actionErrors;  
  15. }  
所以說:對於Action級別的錯誤信息,實際上是放置在ArrayList中的



關於getFieldErrors()的使用誤區
com.opensymphony.xwork2.ActionSupport類之所以非常重要
就是因爲它已經實現了很多很多的接口,而這些接口都是用來處理不同的事情的
在ActionSupport中有很多的方法,其實只要明白了ActionError和FieldError的區別的話
對於這裏的很多關於Error的方法,直接看一下API文檔,然後再跟蹤一下代碼,就都一目瞭然了
有一個在日常開發中,很容易犯錯誤的一個地方,需要強調一下,那就是getFieldErrors()方法
它是這樣的:public Map getFieldErrors()
它的描述是:得到Field級別的錯誤消息,並關聯到當前Action,不應該直接在這裏增加錯誤消息
                 因爲這個實現,可以隨意的返回一個新的Collection或者是不可修改的Collection
先舉個例子:正常情況下是通過this.addFieldError("username","22");往Field中增加一個錯誤信息
但是有人可能有這樣一種思路:先通過this.getFieldErrors()得到一個與Field所對應的LinkedHashMap
然後再執行this.getFieldErrors().put("username", "88");往LinkedHashMap中增加一條信息
但是通過實際操作,運行項目後,發現沒有輸出"88"錯誤信息。這時就需要研究一下getFieldErrors()方法


剖析getFieldErrors()方法

  1. //通過查看父類ActionSupport.java的源碼,查找到了該方法的原形,代碼如下  
  2. public Map getFieldErrors(){  
  3.     return validationAware.getFieldErrors();  
  4. }  
  5. //而validationAwareSupport類中的getFieldErrors()方法的代碼如下所示  
  6. public synchronized Map getFieldErrors(){  
  7.     return new LinkedHashMap(internalGetFieldErrors());  
  8. }  
這時,我們就可以很清楚的知道,它實際上是返回了一個LinkedHashMap的一個副本
實際上this.getFieldErrors().put("username", "88")所增加的信息
是增加到了以前的FieldError的一個副本里面了,根本沒有對以前的FieldError有任何影響
這裏需要注意一下,實際上它並不是真正的return出來了一個原來的集合
而是return出來了一個用原來集合的內容作爲參數的一個LinkedHashMap的一個副本
很多人都會犯這個錯誤
因爲根據我們通常意義上的理解,this.getFieldErrors()應該返回的是一個LinkedHashMap本身
但是實際上它返回的是LinkedHashMap的一個副本。所以在Struts2的API中對該方法有這樣的一段描述
Error messages should not be added directly here
as implementations are free to return a new Collection or an Unmodifiable Collection
這個getFieldErrors就相當於返回了一個只讀的屬性
我們只可以把它get出來,然後讀它的內容,但是不能再往裏面增加或者修改裏面的任何內容


下面是示例工程,這是一個Struts2.0.11應用


首先是web.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  5.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  6.     <filter>  
  7.         <filter-name>struts2</filter-name>  
  8.         <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  
  9.     </filter>  
  10.     <filter-mapping>  
  11.         <filter-name>struts2</filter-name>  
  12.         <url-pattern>/*</url-pattern>  
  13.     </filter-mapping>  
  14.     <welcome-file-list>  
  15.         <welcome-file>validateFrame.jsp</welcome-file>  
  16.     </welcome-file-list>  
  17. </web-app>  

然後是用於提供表單輸入的validateFrame.jsp頁面

  1. <%@ page language="java" pageEncoding="UTF-8"%>  
  2. <%@ taglib prefix="s" uri="/struts-tags"%>  
  3. <s:form action="validateFrame" theme="simple">  
  4.     <table border="9">  
  5.         <tr>  
  6.             <td>姓名</td>  
  7.             <td><s:textfield name="username" id="usernameId"/></td>  
  8.             <%-- 在字段的後面顯示錯誤信息,如此稍顯人性化 --%>  
  9.             <td>  
  10.                 <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold">  
  11.                     <s:param>username</s:param>   
  12.                 </s:fielderror>  
  13.             </td>  
  14.         </tr>  
  15.         <tr>  
  16.             <td>密碼</td>  
  17.             <td><s:password name="password" id="passwordId"/></td>  
  18.             <td>  
  19.                 <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold">  
  20.                     <s:param>password</s:param>   
  21.                 </s:fielderror>  
  22.             </td>  
  23.         </tr>  
  24.         <tr>  
  25.             <td>重複密碼</td>  
  26.             <td><s:password name="repassword" id="repasswordId"/></td>  
  27.             <td>  
  28.                 <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold">  
  29.                     <s:param>repassword</s:param>     
  30.                 </s:fielderror>  
  31.             </td>  
  32.         </tr>  
  33.         <tr>  
  34.             <td>年齡</td>  
  35.             <td><s:textfield name="age"/></td>  
  36.             <td>  
  37.                 <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold">  
  38.                     <s:param>age</s:param>    
  39.                 </s:fielderror>  
  40.             </td>  
  41.         </tr>  
  42.         <tr>  
  43.             <td>生日</td>  
  44.             <td><s:textfield name="birthday"/></td>  
  45.             <td>  
  46.                 <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold">  
  47.                     <s:param>birthday</s:param>   
  48.                 </s:fielderror>  
  49.             </td>  
  50.         </tr>  
  51.         <tr>  
  52.             <td>畢業時間</td>  
  53.             <td><s:textfield name="graduation"/></td>  
  54.             <td>  
  55.                 <s:fielderror cssStyle="font-size:20px;color:red;text-align:left;font-weight:bold">  
  56.                     <s:param>graduation</s:param>     
  57.                 </s:fielderror>  
  58.             </td>  
  59.         </tr>  
  60.         <tr>  
  61.             <td>&nbsp;</td>  
  62.             <td><s:submit value="校驗框架測試"/></td>  
  63.         </tr>  
  64.     </table>  
  65. </s:form>  

當表單輸入域均正確時的validateSuccess.jsp頁面

  1. <%@ page language="java" pageEncoding="UTF-8"%>  
  2. <%@ taglib prefix="s" uri="/struts-tags"%>  
  3. 姓名:<s:property value="username"/><br/>  
  4. 密碼:<s:property value="password"/><br/>  
  5. 年齡:<s:property value="age"/><br/>  
  6. 生日:<s:property value="birthday"/><br/>  
  7. 畢業:<s:property value="graduation"/>  

然後是struts.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE struts PUBLIC   
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0.dtd">  
  5. <struts>  
  6.     <package name="struts2" extends="struts-default">  
  7.         <action name="validateFrame" class="com.jadyer.action.ValidateFrameAction" method="test">  
  8.             <result>/validateSuccess.jsp</result>  
  9.             <result name="input">/validateFrame.jsp</result>  
  10.         </action>  
  11.     </package>  
  12. </struts>  

然後是用到的Action類

  1. package com.jadyer.action;  
  2.   
  3. import java.util.Date;  
  4.   
  5. import com.opensymphony.xwork2.ActionSupport;  
  6.   
  7. @SuppressWarnings({"serial""unused"})  
  8. public class ValidateFrameAction extends ActionSupport {  
  9.     private String username;  
  10.     private String password;  
  11.     private String repassword;  
  12.     private int age;  
  13.     private Date birthday;  
  14.     private Date graduation;  
  15.       
  16.     /* 以上六個屬性的setter和getter略 */  
  17.   
  18.     public String execute() throws Exception {  
  19.         System.out.println("------execute is invoked------");  
  20.         return SUCCESS;  
  21.     }  
  22.     public String test() throws Exception {  
  23.         System.out.println("------test is invoked------");  
  24.         return SUCCESS;  
  25.     }  
  26. }  

最後是用到的驗證框架文件ValidateFrameAction-validation.xml

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"  
  3.                             "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">  
  4. <!-- *************************************************************************************************** -->  
  5. <!-- 一個<field>表示對Action中的一個屬性的校驗,它的name值要與Action的屬性名一致 -->  
  6. <!-- <field-validator/>表示對屬性校驗的方式 -->  
  7. <!-- requiredstring用來校驗String的屬性是必填的,此外都要用required來驗證必填 -->  
  8. <!-- 校驗失敗時,即用戶輸入的信息不符合要求時,就會顯示<message/>中設定的提示信息 -->  
  9. <!-- *************************************************************************************************** -->  
  10. <!-- 而<param name="trim">true</param>則表示忽略掉字符串左右兩邊出現的空格 -->  
  11. <!-- 事實上requiredstring會自動將字符串左右兩邊的空格去掉,所以它可寫可不寫 -->  
  12. <!-- 因爲在RequiredStringValidator源碼中的doTrim屬性默認的就是TRUE -->  
  13. <!-- 雖然RequiredStringValidator中的屬性名是doTrim,但不可以寫成name="doTrim" -->  
  14. <!-- 因爲它真正的值取決於public void setTrim(boolean trim)中的參數的值 -->  
  15. <!-- *************************************************************************************************** -->  
  16. <!-- <field-validator/>還有一個short-circuit屬性,用來表示短路,默認值爲FALSE -->  
  17. <!-- 對於邏輯與來說,前面如果爲假,後面就不再判斷了,直接短路 -->  
  18. <!-- 對於邏輯或來說,前面如果爲真,後面也不再判斷了,直接短路 -->  
  19. <!-- 所以,如果short-circuit的值爲TRUE的話 -->  
  20. <!-- 當username的requiredstring驗證失敗,就不再執行stringlength驗證了 -->  
  21. <!-- *************************************************************************************************** -->  
  22. <!-- 可以使用stringlength驗證字符串的長度,並用minLength和maxLength限定長度範圍 -->  
  23. <!-- 運行時${minLength}就會自動被6替換掉,${maxLength}就會被10替換掉 -->  
  24. <!-- 也可以利用<message/>進行國際化,如<message key="username.xml.invalid"/> -->  
  25. <!-- 無論是字段驗證還是非字段驗證,產生的<message/>信息都會放到FieldError中 -->  
  26. <!-- 所以需要在前臺頁面中使用<s:fielderror/>來顯示錯誤提示信息 -->  
  27. <!-- *************************************************************************************************** -->  
  28. <validators>  
  29.     <field name="username">  
  30.         <field-validator type="requiredstring" short-circuit="true">  
  31.             <param name="trim">true</param>  
  32.             <message>username should not be blank</message>  
  33.         </field-validator>  
  34.         <field-validator type="stringlength">  
  35.             <param name="minLength">6</param>  
  36.             <param name="maxLength">10</param>  
  37.             <message>username should be between ${minLength} and ${maxLength}</message>  
  38.         </field-validator>  
  39.     </field>  
  40.     <!-- **********這裏只列舉出username的非字段校驗寫法,其餘字段寫法與其類似********* -->  
  41.     <!--   
  42.     <validator type="requiredstring">  
  43.         <param name="fieldName">username</param>  
  44.         <message>username should not be blank!</message>  
  45.     </validator>  
  46.     <validator type="stringlength">  
  47.         <param name="fieldName">username</param>  
  48.         <param name="minLength">6</param>  
  49.         <param name="maxLength">10</param>  
  50.         <message>username should be between ${minLength} and ${maxLength}</message>  
  51.     </validator>  
  52.      -->  
  53.     <field name="password">  
  54.         <field-validator type="requiredstring">  
  55.             <message>password should not be blank</message>  
  56.         </field-validator>  
  57.         <field-validator type="stringlength">  
  58.             <param name="minLength">6</param>  
  59.             <param name="maxLength">10</param>  
  60.             <message>password should be between ${minLength} and ${maxLength}</message>  
  61.         </field-validator>  
  62.     </field>  
  63.     <field name="age">  
  64.         <field-validator type="int">  
  65.             <param name="min">1</param>  
  66.             <param name="max">150</param>  
  67.             <message>age should be between ${min} and ${max}</message>  
  68.         </field-validator>  
  69.     </field>  
  70.     <field name="birthday">  
  71.         <field-validator type="required">  
  72.             <message>birthday should not be blank</message>  
  73.         </field-validator>  
  74.         <field-validator type="date">  
  75.             <param name="min">2002-09-09</param>  
  76.             <param name="max">2003-08-28</param>  
  77.             <message>birthday should be between ${min} and ${max}</message>  
  78.         </field-validator>  
  79.     </field>  
  80. </validators>  
  81. <!-- **********關於repassword屬性的校驗,與password類似,故略去********** -->  
  82. <!-- **********關於graduation屬性的校驗,與birthday類似,故略去********** -->  


另附:ValidateFrameAction-validation.xml的補充說明

  1. <!-- ******************【type="fieldexpression"】************************************************************************ -->  
  2. <!-- 下面的password.equals(repassword)不是字符串,而是OGNL表達式 -->  
  3. <!-- 因爲Action中的屬性會被自動放到ValueStack裏面,所以纔可以在這裏使用OGNL -->  
  4. <!-- 通常人們不會將錯誤放到Action級別中,而是普遍性的都放到FieldError中 -->  
  5. <!-- 在進行數據庫驗證,比如用戶名已存在時等等,才把錯誤消息放到ActionError中 -->  
  6. <!-- 另外,如果在Action使用的是領域模型接收表單參數的話,那麼這裏就應該寫成user.password等等 -->  
  7. <!-- 因爲放在ValueStack裏面的是user對象,而不是password屬性 -->  
  8.      <field name="password">  
  9.          <field-validator type="fieldexpression">  
  10.              <param name="expression">password.equals(repassword)</param>  
  11.              <message>密碼不一致</message>  
  12.          </field-validator>  
  13.      </field>  
  14. <!-- ******************【type="visitor"】******************************************************************************** -->  
  15. <!-- 使用visitor驗證類型可以實現驗證框架的複用,所以人們比較喜歡這個驗證類型 -->  
  16. <!-- 在使用的時候,首先<field name="">的name不是某一個字段,而是一個對象 -->  
  17. <!-- 而且該對象必須在validateFrameAction中出現,並提供setXxx和getXxx方法 -->  
  18. <!-- 比如User對象,在validateFrameAction中提供了private User user;及對應的setUser()和getUser()方法 -->  
  19. <!-- 然後新建在com.zhangbing.bean.User.java的包中,即在com.zhangbing.bean包中建立User-validation.xml文件 -->  
  20. <!-- 也就是說此時是對對象進行驗證,然後Struts2會根據Action中的對象找到與之對應的Bean類,也稱VO類 -->  
  21. <!-- 然後就會找到與之同名的User-validation.xml文件,這個文件裏面寫的就是公共的驗證信息 -->  
  22. <!-- 而User-validation.xml返回的信息會通過type="visitor"被嵌套在我們當前的文件中 -->  
  23. <!-- 然後我們在頁面中使用<s:fielderror/>標籤就可以輸出驗證框架所產生的錯誤信息了 -->  
  24.     <field name="user">  
  25.         <field-validator type="visitor">  
  26.             <message>用戶:</message>  
  27.         </field-validator>  
  28.     </field>  
  29. <!-- **********【下面簡單示例一下User-validation.xml中的內容】********** -->  
  30.     <?xml version="1.0" encoding="UTF-8"?>  
  31.     <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"  
  32.                                 "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">  
  33.     <validators>  
  34.         <field name="username">  
  35.             <field-validator type="requiredstring" short-circuit="true">  
  36.                 <param name="trim">true</param>  
  37.                 <message>username should not be blank</message>  
  38.             </field-validator>  
  39.             <field-validator type="stringlength">  
  40.                 <param name="minLength">6</param>  
  41.                 <param name="maxLength">10</param>  
  42.                 <message>username should be between ${minLength} and ${maxLength}</message>  
  43.             </field-validator>  
  44.         </field>  
  45. </validators>  
  46. <!-- ******************【<param name="context">user</param>】************************************************************ -->  
  47. <!-- context參數用來指定上下文的名字,比如這裏定義的上下文是user,則對應User-user-validation.xml校驗文件 -->  
  48. <!-- 其中<param name="appendPrefix">true</param>和<message>user's </message>經常成對出現 -->  
  49. <!-- 參數appendPrefix用來指定是否在顯示給用戶的錯誤消息上添加前綴,而<message>用來指定所添加的文本 -->  
  50.     <field name="user">  
  51.         <field-validator type="visitor">  
  52.             <param name="context">user</param>  
  53.             <param name="appendPrefix">true</param>  
  54.             <message>user's </message>  
  55.         </field-validator>  
  56.     </field>  
  57. <!-- ******************************************************************************************************************** -->  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章