Struts表單校驗插件:Validator框架
一、Validator框架的優勢
Validator框架是一個Struts插件,最初由David Winterfeldt設計并實現。Validator框架從Struts 0.5時代就可以使用,但那時Validator框架只是被捐助的一個jar包。Apache組織為了使開發人員更方便地使用Validator框架,決定從Struts1.1開始,將Validator框架作為Struts的一部分同Struts一起發布。
Validator框架可以在XML文件中配置驗證規則和驗證對象。因此,使用Validator框架可以無需在ActionForm的子類中覆蓋validate方法就可以很方便地驗證客戶端的提交數據。由于Validator框架內置了很多預定義的驗證機制,如驗證某個屬性是否存在,驗證EMail是否合法等。所以在一般情況下,只需要配置XML文件就可以滿足我們的驗證需求。
在使用Validator框架時,就會發現這種方式要比直接使用validate方法進行驗證會給我們帶來如下的好處:
1. 更容易維護。 由于驗證信息可以被放置在同一個配置文件中,因此,我們可以更容易地來維護這些驗證信息。
2. 標準化。由于很多簡單的驗證都是相同的。如用戶名和密碼都要求由字母、數字以及下劃下組成。如果將這些驗證都寫在validate方法中,對這些驗證進行標準化非常困難。而在Validator框架中的這些驗證機制都是預先定義的,因此,標準化相同的驗證對于Validator框架來說將是一件非常輕松的事。
3. 避免重造輪子。雖然一些驗證很簡單,但如果想正確實現它們也是非常困難的。一個典型的例子是驗證EMail地址的格式。如果這個驗證要想完美無缺,就必須按著RFC-2822規范的要求來驗證EMail地址。而如果我們使用Validator框架,就無需再重造輪子來驗證EMail地址了。
4. 減少重復代碼的數量。由于Validator框 架提供了很多預定義的驗證,因此,我們可以避免自己寫很多重復的代碼進行驗證。當然,我們也可以將大量使用的驗證封裝在類的方法中,這些雖然可以避免大量的重復勞動,但這就意味著我們團隊的新成員要使用這些被封裝的驗證方法之前必須先學習它們。而最糟糕的情況是很多開發人員可能會忘記使用這些由其他成員實 現的驗證庫,而自己重新編寫具有同樣功能的驗證庫。當然,這一切如果使用Validator框架就都可以得到解決。
5. 客戶端和服務端驗證自動切換。我們只需要簡單地在JSP頁面中放一個單獨的<html::javascript/>元素就可以將服務端的驗證轉換為客戶端驗證(基于JavaScript的驗證)
雖然Validator框架的預定義驗證已經可以滿足大多數的驗證需求了,但在某些特殊情況下,這些預定義驗證就無法滿足我們的需求了,為此,Validator框架也為開發人員提供了擴展驗證機制的功能。這也使得Validator框架可以完成更復雜的驗證工作。
1. 安裝Validator框架
由于Validator是Struts的一個插件,因此,就需要在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文件。
(1)validator-rules.xml:在這個文件中聲明了Validator框架的預定義驗證。這個文件可以在Struts的發行包的lib目錄中可以找到這個文件。在使用MyEclipse為Web工程添加Struts功能后,會自動將這個文件加到WEB-INF目錄中。
(2)validator.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文件
配置FirstValidatorForm和ValidatorAction的代碼如下所示
<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" /> <font color="red"><html:errors property="name"/></font><p>
年 齡:
<html:text property="age"/> <font color="red"><html:errors property="age"/></font><p>
EMail:
<html:text property="email"/> <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>元素用來定義變量名和變量值。
【第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屬性的每一個值。我們還可以將property和indexedListProperty配合使用,如下面代碼所示:
<field indexedListProperty="items" property="employee.age" depends=> </field>
Validator框架將根據上述的配置代碼來驗證items屬性中的每一項的employee.age屬性。
二、使用常量和變量
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>
三、客戶端驗證
使用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 </td> |
變量 </td> |
引發條件 </td> </tr> | |||||||||||
required </td> |
</td> |
字段只有空格 </td> </tr> | |||||||||||
validwhen </td> |
test </td> |
test條件失敗(詳見下一節) </td> </tr> | |||||||||||
minlength </td> |
minlength </td> |
字段的字符數小于minlength </td> </tr> | |||||||||||
maxlength </td> |
maxlength </td> |
字段的字符數大于maxlength </td> </tr> | |||||||||||
mask </td> |
mask </td> |
字段值不匹配mask所指的個正則表達式 </td> </tr> | |||||||||||
byte、short、integer、long、float、double </td> |
</td> |
字段值無法轉換為這些數據類型 </td> </tr> | |||||||||||
date </td> |
datePattern 或 datePatternStrict </td> |
字值值不能按著指定的格式轉換為日期類型 </td> </tr> | |||||||||||
intRange、floatRange、doubleRange </td> |
min、max </td> |
字段值不在指定的范圍內 </td> </tr> | |||||||||||
creditCard </td> |
</td> |
字段值不是一個信譽卡號 </td> </tr> | |||||||||||
|
</td> |
字段值不是一個合法的email </td> </tr> | |||||||||||
url </td> |
allowallschemes、 allow2slashes、 nofragments、 schemes </td> |
字段不是一個URL </td> </tr> </tbody> </table>關于Validator框架標準驗證的詳細信息,讀者可以訪問如下的URL: http://struts.apache.org/1.2.9/userGuide/dev_validator.html 下面來舉一個validwhen驗證的例子。 <field property="password1" depends="validwhen">
<field property="field1" depends="validwhen"> 其中*this*表示當前屬性的值。 ==================================================================== 一、動態Form簡介 在Struts1.2.6及以后的Struts版本中提供了一種動態Form的技術。使得不用再建立新的ActionForm就可以封裝用戶提交的數據。實際上,這種技術將定義ActionForm子類的工作變成了編寫XML文件的工作。 每定義一個動態Form,就要在struts-config.xml中加一個<form-bean>元素,并使用<form-property>子元素來定義動態Form的屬性。 在本章的最后還會介紹一個LazyValidatorForm類,通過這個類甚至可以不定義動態Form的屬性就可以使用動態Form。這將大大簡化開發人員的工作量。 二、聲明動態Form 聲明一個動態Form非常簡單,只需要在struts- config.xml的<form-beans>元素中加入一個<form-bean>子元素,并使用<form- property>元素來定義動態Form的屬性。我們可以定義的屬性類型有簡單屬性(如String)、索引屬性(如數組)、映射屬性(如 HashMap)以及嵌套屬性(屬性類型是另一個類)。 <form-bean name="dynamicForm" type="org.apache.struts.action.DynaActionForm"> 三、動態Form的屬性類型 下面列出了動態Form支持的簡單屬性的所有類型:
實際上,上面的數據類型就是Java中提供了簡單數據類型。它們用在動態Form中和在Java中代表的數據類型是完全一樣的。我們還可以使用<form-property>元素的initial屬性為動態Form的簡單屬性指定一個默認值。如在例程6-11中name屬性的默認值為“bill”。 對于索引屬性的類型來說,可以是數組,也可以是java.util.List接口的類(如ArrayList)。我們還可以為動態Form的屬性指定實現java.util.Map接口的類作為數據類型(也就是映射屬性)。但遺憾的是,如果使用動態Form,就無法使用泛型進行自動類型轉換了。 四、訪問動態Form public Object get(String name) ; // 讀取簡單屬性 DynaActionForm dForm = (DynaActionForm)form; 除了上述的get方法外,DynaActionForm還提供了getString和getString方法,分別用來讀取String和String[]類型的屬性值,這兩個方法的定義如下: public String getString(String name) ; 下面的代碼演示了如何通過getString和getStrings方法獲得動態Form的屬性值: String name = dForm.getString(“name”); // 相當于String name = (String)dForm.get("name"); 在使用getString和getStrings方法時應注意,這兩個方法只能讀取String或String[]類型的屬性,讀取其他類型的屬性將會拋出異常。 五、一個動態Form的例子 我們在這一部分來實現一個完整的動態Form的例子,在這個例子中的動態Form有四個屬性,三個是簡單數據類型,一個是數組類型。完成這個例子需要如下四步: <form-bean name="dynamicForm" type="org.apache.struts.action.DynaActionForm"> 【第2步】編寫Struts Action類 package chapter6.action; 【第3步】配置Struts Action 打開struts-config.xml文件,在<action-mappings>元素中加入如下的內容: <action name="dynamicForm" path="/dynamic" scope="request" type="action.DynamicAction" />
<%@ page pageEncoding="GBK"%>
六、驗證動態Form 有兩種方法可以驗證動態Form: 1. 在DynaActionForm的子類中覆蓋validate方法。 2. 如果要使用Validator框架來驗證動態Form,需要用DynaActionForm的子類org.apache.struts.validator. DynaValidatorForm或其子類來作為動態Form的類型。 在使用DynaValidatorForm的了類時,要想使用Validator框架的驗證機制,需要在DynaValidatorForm子類的validate方法的開始位置使用 super.validate()語句來調用DynaValidatorForm中的validate方法。</span></span></span> 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!
相關經驗相關資訊 |