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框架能夠完成更復雜的驗證工做。
數組
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屬性。
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所指的個正則表達式 |
byte、short、integer、long、float、double |
|
字段值沒法轉換爲這些數據類型 |
date |
datePattern 或 datePatternStrict |
字值值不能按着指定的格式轉換爲日期類型 |
intRange、floatRange、doubleRange |
min、max |
字段值不在指定的範圍內 |
creditCard |
|
字段值不是一個信譽卡號 |
|
|
字段值不是一個合法的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中提供了簡單數據類型。它們用在動態Form中和在Java中表明的數據類型是徹底同樣的。咱們還可使用<form-property>元素的initial屬性爲動態Form的簡單屬性指定一個默認值。如在例程6-11中name屬性的默認值爲「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還提供了getString和getString方法,分別用來讀取String和String[]類型的屬性值,這兩個方法的定義以下:
public String getString(String name) ;
public String[] getStrings(String name) ;
下面的代碼演示瞭如何經過getString和getStrings方法得到動態Form的屬性值:
String name = dForm.getString(「name」); // 至關於String name = (String)dForm.get("name");
String[] hobbies = dForm.getStrings(「hobbies」); // 至關於String[] hobbies = (String[])dForm.get(「hobbies」);
在使用getString和getStrings方法時應注意,這兩個方法只能讀取String或String[]類型的屬性,讀取其餘類型的屬性將會拋出異常。
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" /> <p>
年 齡:<html:text property="age" /> <p>
工 資:<html:text property="salary" /> <p>
愛好1:<html:text property="hobby" value=""/> <p>
愛好2:<html:text property="hobby" value=""/> <p>
愛好3:<html:text property="hobby" value=""/> <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方法。