【Struts2】Struts2學習(5)類型轉換和輸入校驗

Struts2類型轉換

MVC框架需要負責解析HTTP請求參數,並將請求參數傳給控制器組件,Http請求參數都是字符串類型,此時MVC框架必須將這些字符串參數轉換成相應的數據類型。

 

Struts2內建類型轉換器

Struts2可以完成大多數常用類型轉換,這些是通過Struts2內建的類型轉換器完成的。包括以下boolean/char/int/long/float/double/Date/數組/集合

數組:默認情況下,數組元素是字符串,如果用戶提供了自定義類型轉換器,也可以是其他複合類型的數組。

集合:默認情況下,既定集合元素類型是String,並創建一個新的ArrayList封裝所有字符串。

 

基於OGNL的類型轉換

藉助OGNL表達式的支持,Struts2允許以另一種簡單的方式將請求轉換成複合類型。

LoginAction.java

public class LoginAction implements Action
{
	//User類型屬性封裝請求參數
	private User user;
	private String tip;
	//user屬性的setter和getter方法
	…
	public String execute() throws Exception
	{
		//通過user屬性的name屬性和pass屬性來判斷控制邏輯
		if (getUser().getName().equals("crazyit.org")
			&& getUser().getPass().equals("leegang") )
		{
			setTip("登錄成功");
			return SUCCESS;
		}
		else
		{
			setTip("登錄失敗!!");
			return ERROR;
		}
	}
}
User.java

public class User
{
	private String name;
	private String pass;

	//name屬性的setter和getter方法
}
input.jsp

<s:form action="login">
	<!-- 該表單域封裝的請求參數名爲user.name -->
	<s:textfield name="user.name" label="用戶名"/>
	<!-- 該表單域封裝的請求參數名爲user.pass -->
	<s:textfield name="user.pass" label="密碼"/>
	<tr>
		<td colspan="2"><s:submit value="轉換" theme="simple"/>
		<s:reset value="重填" theme="simple"/></td>
	</tr>
</s:form>
welcome.jsp

用戶名爲:<s:property value="user.name"/><br/>
密碼爲:<s:property value="user.pass"/><br/>

在上面代碼中,Action裏包含了一個User類型的屬性,這個屬性需要進行類型轉換,Struts2框架接收到HTTP請求參數後,需要把這些請求參數封裝成User對象。

使用OGNL時無需做任何特殊處理,只需要在定義表單域時使用OGNL表達式來定義表單域的name屬性。

使用這種方式時需要注意:

1.      Struts2將通過反射來創建一個複合類(User類)的實例,所以必須爲該類提供無參數構造器。

2.      需要爲屬性提供get/set方法。

 

Map類型

LoginActionMap.java

public class LoginActionMap implements Action
{
	//Action類裏包含一個Map類型的參數
	//Map的value類型爲User類型
	private Map<String , User> users;
	private String tip;
	//屬性的setter和getter方法
	public String execute() throws Exception
	{
		//在控制檯輸出Struts 2封裝產生的List對象
		System.out.println(getUsers());
		//根據Map集合中key爲one的User實例來決定控制邏輯
		if (getUsers().get("one").getName().equals("li")
			&& getUsers().get("one").getPass().equals("meng") )
		{
			setTip("登錄成功!");
			return SUCCESS;
		}
		else
		{
			setTip("登錄失敗!!");
			return ERROR;
		}
	}
}
inputmap.jsp

<s:form action="loginmap">
	<s:textfield name="users['one'].name" label="第one個用戶名"/>
	<s:textfield name="users['one'].pass" label="第one個密碼"/>
	<s:textfield name="users['two'].name" label="第two個用戶名"/>
	<s:textfield name="users['two'].pass" label="第two個密碼"/>
	<tr>
		<td colspan="2"><s:submit value="轉換" theme="simple"/>
		<s:reset value="重填" theme="simple"/></td>
	</tr>
</s:form>

上面粗體代碼使用OGNL表達式通過“屬性名[‘key值’].屬性名”來爲Map對象賦值。

welcomemap.jsp

<s:property value="tip"/><br/>
	key爲one的用戶名爲:<s:property value="users['one'].name"/><br/>
	key爲one的密碼爲:<s:property value="users['one'].pass"/><br/>
	key爲two的用戶名爲:<s:property value="users['two'].name"/><br/>
	key爲two的密碼爲:<s:property value="users['two'].pass"/><br/>
如果要把users屬性改爲List<User> 一樣可以使用OGNL表達式,只需要修改爲

<s:form action="login">
	<s:textfield name="users[0].name" label="第一個用戶名"/>
	<s:textfield name="users[0].pass" label="第一個密碼"/>
	<s:textfield name="users[1].name" label="第二個用戶名"/>
	<s:textfield name="users[1].pass" label="第二個密碼"/>
	<tr>
		<td colspan="2"><s:submit value="轉換" theme="simple"/>
		<s:reset value="重填" theme="simple"/></td>
	</tr>
</s:form>

指定集合元素的類型

前面使用集合都使用了泛型,使用泛型可以讓Struts2瞭解集合元素的類型,就可以通過反射來創建對應類的對象,並將這些對象添加到List中。

  如果不使用泛型,那麼Struts2就不知道使用類型轉換器來處理users屬性,但Struts2允許開發者通過局部類型轉換文件來指定集合元素類型。類型轉換文件就是一個普通的Properties(*.properties)文件,類型轉換文件裏提供了類型轉換的相關配置信息。

LoginAction.java

public class LoginActionList implements Action
{
    //沒有爲users指定泛型
	private List users;
}

局部類型轉換文件的文件名應爲 ActionName-conversion.properties形式,其中ActionName是需要Action的類名,後面的–conversion.properties 字符串則是固定部分。類型裝換文件應該放在和Action類文件相同的位置。

爲了指定List集合裏元素的數據類型,需要指定兩個部分:

         List集合屬性的名稱。

         List集合裏元素的類型。

通過在局部類型轉換文件裏指定如下key-value對

Element_<ListPropName>=<ElementType>
如: Element_users=org.crazyit.app.domain.User
如果對於Map類型的屬性,則需要同時指定Map的key類型和value類型。爲了指定Map類型屬性的key類型,應該在局部類型裝換文件增加如下項:
Key_<MapPropName>=<KeyType>
爲了指定Map屬性例的value類型,應該增加如下項:

Element_<MapPropName>=<ValueType>

自定義類型轉換器

有些特殊情況下,如需要把一個字符串轉換成一個複合對象(例如User),這時候就需要使用自定義類型轉換器。例如,把abc,def字符串轉換成User的用戶名和密碼,此時通過Struts框架是不能完成的,我們需要自定義類型轉換器。

Struts2的類型轉換器是基於OGNL框架的,在OGNL中有一個TypeConverter接口,這個接口就是自定義類型轉換器必須實現的接口。該接口的定義代碼爲:

//OGNL提供的類型轉換器接口
public interface TypeConverter{
    public Object converValue(Map context,Object target,Member member,String propertyName,Object value,Class toType);
}
實現類型轉換器必須實現上面的接口,但該接口的方法太過複雜,所以OGNL項目爲該接口實現了一個實現類:DefaultTypeConverter,通常都採用擴展該類來實現自定義類型轉換器。實現自定義類型轉換器需要重寫DefaultTypeConverter類的converValue方法。

public class UserConverter extends DefaultTypeConverter 
{
	//類型轉換器必須重寫convertValue方法,該方法需要完成雙向轉換
	public Object convertValue(Map context
		, Object value, Class toType)
	{
		//當需要將字符串向User類型轉換時
		if (toType == User.class )
		{
			//系統的請求參數是一個字符串數組
			String[] params = (String[])value;
			//創建一個User實例
			User user = new User();
			//只處理請求參數數組第一個數組元素,
			//並將該字符串以英文逗號分割成兩個字符串
			String[] userValues = params[0].split(",");
			//爲User實例賦值
			user.setName(userValues[0]);
			user.setPass(userValues[1]);
			//返回轉換來的User實例
			return user;
		}
		else if (toType == String.class )
		{
			//將需要轉換的值強制類型轉換爲User實例
			User user = (User) value;
			return "<" + user.getName() + ","
				+ user.getPass() + ">";
		} 
		return null ;
	} 
}

convertValue方法負責完成類型的轉換,不過這種轉換是雙向的。

註冊類型轉換器

 

1.       註冊局部類型轉換器:局部類型轉換器僅僅對某個Action屬性起作用。

註冊局部類型轉換器使用局部類型轉換文件指定,主要在局部類型轉換文件中增加

<propName>=<ConverterClass>

如:user=org.crazyit.app.converter.UserConverter

2.       註冊全局類型轉換器:全局類型轉換器對所有Action的特定類型的屬性都會生效。

註冊全局類型轉換器應該提供一個xwork-conversion.properties文件,該文件就是全局類型轉換文件。該文件直接放在WEB-INF/classes或 src下。

全局類型轉換器由多項<propType>=<ConvertClass> 項組成,將<propType>替換成需要進行類型轉換的類型。如:

org.crazyit.app.domain.User=org.crazyit.app.converter.UserConverter

基於Struts2的自定義類型轉換器

爲了簡化類型轉換器的實現,Struts2提供了一個StrutsTypeConverter抽象類,這個抽象類是DefaultTypeConverter類的子類。StrutsTypeConverter類簡化了類型轉換器的實現,該類已經實現了DefaultTypeConverter的convertValue方法,實現該方法時,它將兩個不同方向的轉換轉化爲了兩個方法,如下:

public class UserConverter extends StrutsTypeConverter 
{
	//實現將字符串類型轉換成複合類型的方法
	public Object convertFromString(Map context
		, String[] values , Class toClass)
	{
		//創建一個User實例
		User user = new User();
		//只處理請求參數數組第一個數組元素,
		//並將該字符串以英文逗號分割成兩個字符串
		String[] userValues = values[0].split(",");
		//爲User實例賦值
		user.setName(userValues[0]);
		user.setPass(userValues[1]);
		//返回轉換來的User實例
		return user;
	}
	//實現將複合類型轉換成字符串類型的方法
	public String convertToString(Map context, Object o)
	{
		//將需要轉換的值強制類型轉換爲User實例
		User user = (User) o;
		return "<" + user.getName() + ","
			+ user.getPass() + ">";
	}
}

類型轉換中的錯誤處理

表現層數據涉及兩個處理:數據校驗和類型轉換是密切相關的,只有當輸入數據是有效數據時,系統纔可以進行有效的數據類型轉換。

Struts2提供了一個名爲conversionError的攔截器,這個攔截器被註冊在默認的攔截器棧中。查看默認配置文件struts-default.xml,可以看到如下配置

<interceptor-stack name=”defaultStack”>
    <interceptor-ref name=”conversionError”/>
</interceptor-stack>

爲了讓Struts2類型轉換的錯誤處理機制生效,必須讓Action繼承Struts2的ActionSupport基類。

增加input邏輯視圖

<action name="loginerrorhandler" class="org.crazyit.app.action.LoginActionErrorHandler">
			<!-- 配置名爲input的邏輯視圖,
				當轉換失敗後轉入該邏輯視圖 -->
			<result name="input">/inputerrorHandler.jsp</result>
			<result name="success">/welcomeerrorHandler.jsp</result>
			<result name="error">/welcomeerrorHandler.jsp</result>
</action>

Struts2的輸入校驗

客戶端校驗進行基本校驗,如校驗非空字段是否爲空,數字格式是否正確等。客戶端校驗主要用來過濾用戶的誤操作。客戶端校驗的作用是:拒絕誤操作輸入提交到服務器處理,降低服務器負擔。主要通過JavaScript代碼完成。

服務器校驗防止非法數據進入程序,導致程序異常、底層數據庫異常。服務器端校驗是保證程序有效運行及數據完整的手段。

校驗規則文件

表單代碼:

<s:fielderror/>
<s:form action="regist">
	<s:textfield name="name" label="用戶名"/>
	<s:textfield name="pass" label="密碼"/>
	<s:textfield name="age" label="年齡"/>
	<s:textfield name="birth" label="生日"/>
	<s:submit value="註冊"/>
</s:form>

這四個表單域需要滿足如下規則:

name和pass只能是字母和數字,且長度必須在4到25之間。

年齡必須是1到150之間的整數。

生日必須在1900-1-1和2050-02-21之間

該表單對應的Action爲:

public class RegistAction extends ActionSupport
{
	private String name;
	private String pass;
	private int age;
	private Date birth;
	//name屬性的setter和getter方法
}

該Action繼承ActionSupport類,因此默認包含一個execute方法,且該方法直接返回success字符串,這個Action不具備任何輸入校驗功能。

通過爲該Action指定一個輸入校驗文件,就可以利用Struts2的輸入校驗功能對該Action進行校驗。

<?xml version="1.0" encoding="GBK"?>
<!-- 指定校驗配置文件的DTD信息 -->
<!DOCTYPE validators PUBLIC 
	"-//OpenSymphony Group//XWork Validator 1.0.3//EN"
	"http://www.opensymphony.com/xwork/xwork-validator-1.0.3.dtd">
<!-- 校驗文件的根元素 -->
<validators>
	<!-- 校驗Action的name屬性 -->
	<field name="name">
		<!-- 指定name屬性必須滿足必填規則 -->
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message>必須輸入名字</message>
		</field-validator>
		<!-- 指定name屬性必須匹配正則表達式 -->
		<field-validator type="regex">
			<param name="expression"><![CDATA[(\w{4,25})]]></param>
			<message>您輸入的用戶名只能是字母和數字
				,且長度必須在4到25之間</message>
		</field-validator>
	</field>
	<!-- 校驗Action的pass屬性 -->
	<field name="pass">
		<!-- 指定pass屬性必須滿足必填規則 -->
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message>必須輸入密碼</message>
		</field-validator>
		<!-- 指定pass屬性必須滿足匹配指定的正則表達式 -->
		<field-validator type="regex">
			<param name="expression"><![CDATA[(\w{4,25})]]></param>
			<message>您輸入的密碼只能是字母和數字
				,且長度必須在4到25之間</message>
		</field-validator>
	</field>
	<!-- 指定age屬性必須在指定範圍內-->
	<field name="age">
		<field-validator type="int">
			<param name="min">1</param>
			<param name="max">150</param>
			<message>年紀必須在1到150之間</message>
		</field-validator>
	</field>
	<!-- 指定birth屬性必須在指定範圍內-->
	<field name="birth">
		<field-validator type="date">
			<!-- 下面指定日期字符串時,必須使用本Locale的日期格式 -->
			<param name="min">1900-01-01</param>
			<param name="max">2050-02-21</param>
			<message>生日必須在${min}到${max}之間</message>
		</field-validator>
	</field>
</validators>
該校驗文件的文件名應該遵循,且保存在和Action class文件相同的路徑下。

<Action 名字>-validation.xml
輸入校驗失敗後,Struts2也是自動返回名爲 “input”的Result,因此需要在struts.xml文件中配置名爲“input”的Result。
<action name="regist" class="org.crazyit.app.action.RegistAction">
			<!-- 類型轉換失敗、輸入校驗失敗,轉入該頁面 -->
			<result name="input">/regist.jsp</result>
			<result>/show.jsp</result>
</action>

國際化提示信息

以上校驗文件提示信息是通過硬編碼的方式寫在配置文件中的,這種方式不利於程序國際化。我們爲message元素指定key屬性,實現國際化。
<validators>
	<!-- 校驗Action的name屬性 -->
	<field name="name">
		<!-- 指定name屬性必須滿足必填規則 -->
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message key="name.requried"/>
		</field-validator>
		<!-- 指定name屬性必須匹配正則表達式 -->
		<field-validator type="regex">
			<param name="expression"><![CDATA[(\w{4,25})]]></param>
			<message key="name.regex"/>
		</field-validator>
	</field>
	<!-- 校驗Action的pass屬性 -->
	<field name="pass">
		<!-- 指定pass屬性必須滿足必填規則 -->
		<field-validator type="requiredstring">
			<param name="trim">true</param>
			<message key="pass.required"/>
		</field-validator>
		<!-- 指定pass屬性必須滿足匹配指定的正則表達式 -->
		<field-validator type="regex">
			<param name="expression"><![CDATA[(\w{4,25})]]></param>
			<message key="pass.regex"/>
		</field-validator>
	</field>
	<!-- 指定age屬性必須在指定範圍內-->
	<field name="age">
		<field-validator type="int">
			<param name="min">1</param>
			<param name="max">150</param>
			<message key="age.range"/>
		</field-validator>
	</field>
	<!-- 指定birth屬性必須在指定範圍內-->
	<field name="birth">
		<field-validator type="date">
			<!-- 下面指定日期字符串時,必須使用本Locale的日期格式 -->
			<param name="min">1900-01-01</param>
			<param name="max">2050-02-21</param>
			<message key="birth.range"/>
		</field-validator>
	</field>
</validators>

使用客戶端校驗

在Struts2中使用客戶端校驗,只需要修改兩個地方。

1.      將輸入頁面的表單元素全部使用Struts2標籤來生成表單。

2 .     爲該<s:form…/>元素增加validate=”true”屬性。

<s:fielderror/>
<s:form action="regist" validate="true">
	<s:textfield name="name" label="用戶名"/>
	<s:textfield name="pass" label="密碼"/>
	<s:textfield name="age" label="年齡"/>
	<s:textfield name="birth" label="生日"/>
	<s:submit value="註冊"/>
</s:form>
根據MVC思想,我們不應該直接請求頁面,所以在struts.xml中配置一個action

<action name="*">
	<result>/{1}.jsp</result>
</action>

發送請求,點擊提交,該頁面的地址依然停留在原來的頁面,並未提交到對應的Action。這表明:尚明的數據校驗是客戶端完成的。

客戶端校驗依然是基於JavaScript完成的,因爲JavaScript腳本本身的限制,有些服務器校驗不能轉換成客戶端校驗。

客戶端校驗僅僅支持如下幾種校驗器。

required validator(必填校驗器)

requiredstring validator(必填字符串校驗器)

stringlength validator(字符串長度校驗器)

regex validator(表達式校驗器)

email validator(郵件校驗器)

url validator(網址校驗器)

int validator(整數校驗器)

double validator(雙精度數校驗器)

客戶端校驗有如下三個值得注意的地方

Struts2 的<s:form …/>元素有一個theme屬性,不要將該屬性指定爲simple。

瀏覽者不能直接訪問啓用客戶端校驗的表單頁,這樣會應發異常。我們可以把啓用客戶端校驗的表單頁放到WEB-INF路徑下去,讓瀏覽訪問所有資源之前都先經過他的核心Filter。

啓用客戶端校驗的表單頁面的action和namespace要分開寫,例如我們向namespace爲/lee , name 爲 registPro的Action請求, 應寫成 <s:form action=”registPro” namespace=”/lee”> 而不應該寫成<s:form action=”lee/registPro”>

字段校驗器配置風格

struts2提供了兩種方式來配置校驗規則:字段校驗器風格和非字段校驗器風格。這兩種風格沒有本質不同,知識組織校驗規則的方式不同:一種是字段優先,稱爲字段校驗器風格,另一種是校驗器優先,稱爲非字段校驗器風格。

查看 xwork-validator-1.0.3.dtd文件,有如下定義:

<!ELEMENT validators (field | validator)+>

在validators元素的field或validator中都可以出現一次或無限多次。

字段校驗器風格:

<field name=”被校驗的字段”>
<field-validator type=”校驗器名”>
  <!—此處需要爲不同校驗器指定校驗參數 -->
<param name = “參數名”>參數值</param>
  <!—校驗失敗後的提示信息,其中key指定國際化信息的key-->
  <message key=”I18Nkey”>校驗失敗提示信息</message>
</field-validator>
<!—如果該字段滿足多個規則,可配置多個校驗器-->
</field>
非字段校驗風格,採用非字段校驗器風格的校驗規則文件,<validators …/> 元素下有多個<validator …/> 元素,每個<validators …/> 元素都有如下格式:

<validator type =”校驗器”>
   <param name=”fieldName”>需要被校驗的字段</param>
  <!—此處需要爲不同校驗器指定校驗參數 -->
  <param name = “參數名”>參數值</param>
  <!—校驗失敗後的提示信息,其中key指定國際化信息的key-->
  <message key=”I18Nkey”>校驗失敗提示信息</message>
</validator>

注意:並不是所有的校驗器都支持兩種配置風格。

短路校驗器

<validator…/>元素和<field-validator …/> 元素可以指定一個可選的short-circuit屬性,這個屬性指定該校驗器是否是短路校驗器,默認是false

前面的校驗中會一次性輸出所有的校驗提示信息,這種是非常不友好的,我們完全沒有輸入一個字段,提示就出來了,比較好的做法是:如果用戶完全沒有爲某個輸入框輸入任何內容,系統應該僅輸出第一行提示信息,而不是一次性輸出。

<field name="name" >
		<!-- 指定name屬性必須滿足必填規則 -->
		<field-validator type="requiredstring" short-circuit="true">
			<param name="trim">true</param>
			<message key="name.requried"/>
		</field-validator>
		<!-- 指定name屬性必須匹配正則表達式 -->
		<field-validator type="regex">
			<param name="expression"><![CDATA[(\w{4,25})]]></param>
			<message key="name.regex"/>
		</field-validator>
	</field>

配置成短路校驗器之後,如果一個校驗器失敗,其他校驗器就不會繼續校驗。

校驗文件搜索規則

一個Action可能包含了多個處理邏輯,當一個Action類中包含多個類似於execute的方法時,每個方法都是一個處理邏輯。不同的處理邏輯可能需要不同的校驗規則,Struts2允許爲不同的控制邏輯指定不同校驗規則的支持。

在struts.xml中將Action類配置成兩個邏輯Action。

<action name="*Pro" class="org.crazyit.app.action.RegistAction"
			method="{1}">
			<result name="input">/WEB-INF/content/form.jsp</result>
			<result>/WEB-INF/content/show.jsp</result>
</action>
爲了能精確控制每個校驗邏輯,Struts允許通過爲校驗文件增加Action別名來指定具體的需要校驗的處理邏輯

<ActionClassName>-<ActionAliasName>-validation.xml

其中ActionClassName是Action處理類的類名,而ActionAliasName就是在struts.xml中配置Action時所指定的name屬性。如果我們需要爲loginPro邏輯Action單獨指定校驗文件,則校驗文件的文件名爲RegistAction-loginAction-validation.xml

名爲loginPro的Action中包含的校驗規則是RegistAction-validation.xml和 RegistAction-loginPro-validation.xml 兩個文件中規則的總和。

 

還有另外一種情形:系統中包含了兩個Action:BaseAction和RegistAction,其中RegistAction繼承了BaseAction,且兩個Action都指定了對應的配置文件,則RegistAction對應Action的校驗規則實際上是RegistAction-validation.xml和 BaseAction-validation.xml兩個文件中規則的總和。

假設系統有兩個Action: BaseAction 和RegistAction,則系統搜索規則文件順序如下:

(1)BaseAction-validation.xml

(2)BaseAction-別名-validation.xml

(3)RegistAction-validation.xml

(4)RegistAction-別名-validation.xml

這種搜索與其他搜索不同的是,即使找到第一個校驗規則,系統還會繼續搜索,不管有沒有這4份文件,也不管是否找到配置文件,系統總是按固定順序搜索。

struts2搜索規則文件是從上而下的,實際用的校驗規則是所有校驗規則的總和,如果兩個校驗規則衝突,則後面的文件取勝。

 

校驗器的執行順序有如下原則:

所有非字段風格的校驗器優先於字段風格的校驗器。

所有非字段風格的校驗器中,排在前面的會先執行。

所有字段風格的校驗器中,排在前面的會先執行。

校驗器短路的原則:

所有非字段校驗器是最優先執行,如果某個非字段校驗器失敗了,則該字段上所有字段校驗器都不會得到校驗機會。

  非字段校驗器的校驗失敗,不會阻止其他非字段校驗器的執行。

  如果一個字段校驗器校驗失敗後,不會阻止其他非字段校驗的執行。

  如果一個字段校驗失敗後,則該字段下且排在該校驗失敗的校驗器之後的其他字段校驗器不會獲得校驗的機會。

  字段校驗器永遠不會阻止非字段校驗器的執行。

打開Struts 2 的 xwork-2.2.1.jar文件,在com/opensymphony/xwork2/validator/validators/default.xml文件,這個文件就是Struts2默認的校驗器註冊文件。

<validators>
  <validator name=”required” class=”com.opensymphony.xwork.validator.validators.RequiredFieldValidator”
 ……
</validators>
通過上面代碼可以看出,通過<validator …/> 註冊一個校驗器name屬性指定該校驗器的名字,classs屬性指定該校驗器的實現類,如果開發了一個自己的校驗器,可以通過添加一個validators.xml來註冊校驗器。如果Struts2在WEB-INF/classes路徑下找到一個validator.xml文件,則不會再加載系統默認的default.xml。所以如果提供自己的校驗註冊文件,則需要把default.xml文件的內容全部拷貝到validators.xml中。

 

必填校驗器: required,該校驗器要求指定字段必須有值,可接受如下參數。

fieldname: 該參數指定校驗的Action屬性名,如果採用字段校驗風格,則無需指定。

非字段風格:

<validators>

  <validator type=”required”>

<param name=”fieldName”>username</param>

<message> username must not be null</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”username”>

<field-validator type=”required”>

  <message>username must not be null </message>

</field-validator>

  </field>

</validators>

必填字符串校驗器: requiredstring 該校驗器要求字段值必須非空且長度大於0,即該字符串不能是“”,可接受如下參數:

filename: 該參數指定校驗的Action屬性名,如果採用字段校驗風格,則無需指定該參數。

trim : 是否在校驗前截斷被校驗屬性前後的空白,該屬性是可選的,默認是true。

非字段風格:

<validators>

  <validator type=”requiredstring”>

<param name=”fieldName”>username</param>

<param name=”trim”>true</param>

<message> username must not be null</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”username”>

<field-validator type=”requiredstring”>

  <param name=”trim”>true</param>

  <message>username must not be null </message>

</field-validator>

  </field>

</validators>

整數校驗器  整數校驗器包括int long short ,該校驗器要求字段的整數值必須在指定範圍內。該校驗器可以接收如下參數

fieldname : 該參數指定校驗的Action屬性名,如果採用字段校驗器風格,則無需指定。

min: 指定該屬性的最小值,該參數可選,如果沒有指定,則不檢查最小值。

max:指定該屬性的最大值,該參數可選,如果沒有指定,則不檢查最大值。

非字段風格:

<validators>

  <validator type=”int”>

<param name=”fieldName”>age</param>

<param name=”min”>20</param>

<param name=”max”>50</param>

<message> age needs to be between ${min} and ${max}</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”age”>

<field-validator type=”int”>

  <param name=”min”>20</param>

<param name=”max”>50</param>

<message> age needs to be between ${min} and ${max}</message>

</field-validator>

  </field>

</validators>

日期校驗器  date  該校驗器要求字段的日期值必須在指定範圍內。該校驗器可以接收如下參數:

fieldname : 該參數指定校驗的Action屬性名,如果採用字段校驗器風格,則無需指定。

min: 指定該屬性的最小值,該參數可選,如果沒有指定,則不檢查最小值。

max:指定該屬性的最大值,該參數可選,如果沒有指定,則不檢查最大值。

非字段風格:

<validators>

  <validator type=”date”>

<param name=”fieldName”>birth</param>

<param name=”min”>1990-01-01</param>

<param name=”max”>2010-01-01</param>

<message> Birthday needs to be between ${min} and ${max}</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”age”>

<field-validator type=”date”>

  <param name=”min”>1990-01-01</param>

<param name=”max”>2010-01-01</param>

<message> Birthday needs to be between ${min} and ${max}</message>

</field-validator>

  </field>

</validators>

表達式校驗器 expression 它是一個非字段校驗器,不可在字段校驗器的配置風格中使用。表達式校驗器要求OGNL表達式返回true,當返回true時,該校驗通過;否則校驗沒有通過。該校驗器可以接收如下一個參數。

expression: 該參數指定一個邏輯表達式,該邏輯表達式基於ValueStack進行求值,最後返回一個Boolean值,當返回true時,校驗通過,否則校驗失敗。

<validators>

  <validator type=”expression”>

<!—指定校驗表達式-->

<param name=”expression”> …</param>

<message>Failed to meet OGNL expression</message>

  </validator>

</validators>

字段表達式校驗器 fieldexpression 它要求指定字段滿足一個邏輯表達式。該校驗器可以接受如下兩個參數。

fieldname : 該參數指定校驗的Action屬性名。如果採用字段校驗器風格,則無需指定。

expression: 該參數指定一個邏輯表達式,該邏輯表達式基於ValueStack進行求值,最後返回一個Boolean值,當返回true時,校驗成功。

非字段風格:

<validators>

  <validator type=”fieldexpression”>

<param name=”fieldName”>pass</param>

<param name=”expression”><![CDATA[(pass == rpass)]]></param>

<message> 密碼必須和確認密碼相同</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”pass”>

<field-validator type=”fieldexpression”>

<param name=”expression”><![CDATA[(pass == rpass)]]></param>

<message> 密碼必須和確認密碼相同</message>

</field-validator>

  </field>

</validators>

郵件地址校驗器  email  它要求被檢查字段的字符如果非空,則必須是合法的郵件地址,這個校驗器實際就是基於正則表達式進行校驗的。系統的正則表達式可能不能完全覆蓋實際的電子郵件地址,所以建議使用正則表達式校驗器來完成郵件校驗。

該校驗器可以接受如下一個參數

fieldname 該參數指定校驗的Action屬性名,如果採用字段風格,則無需指定。

非字段風格:

<validators>

  <validator type=”email”>

<param name=”fieldName”>email</param>

<message> 你的電子郵件地址不是一個有效地址</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”email”>

<field-validator type=”email”>

<message>你的電子郵件地址不是一個有效地址</message>

</field-validator>

  </field>

</validators>

網址校驗器  url  它要求被檢查字段的字符如果非空,則必須是合法的URL地址。也是基於正則表達式的,所以有可能不能全覆蓋,建議使用正則表達式校驗器。

該校驗器可以接收如下參數

fieldname 該參數指定校驗的Action屬性名,如果採用字段風格,則無需指定。

非字段風格:

<validators>

  <validator type=”url”>

<param name=”fieldName”>url</param>

<message> 你的網址不是一個有效地址</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”url”>

<field-validator type=”url”>

<message>你的網址不是一個有效地址</message>

</field-validator>

  </field>

</validators>

Vistor校驗器  Vistor校驗器用於檢測Action裏的複合屬性,例如一個Action裏包含了User類型的屬性。User類包含若干個字段,如果要校驗Action的User屬性,顯然不能通過其他校驗器完成,因爲那些普通校驗器都只能校驗基本數據類型和字符串類型。

<validators>

  <field name = “user”>

<field-validator type=”vasitor”

  <param name=”context”>userContext</param>

  <!—指定校驗失敗後提示信息是否添加下面前綴-->

  <param name=”appendPrefix”>true</param>

  <message>用戶的:</message>

</field-validator>

  </field>

</validators>

我們還必須爲User類指定對應的校驗規則文件。默認情況下,該校驗文件的規則文件名爲User-validation.xml 因爲配置Visitor校驗器時指定了context 爲userContext ,該校驗文件的文件名爲User-userContext-validation.xml 該文件需要與User.class 相同路徑。

轉換校驗器 conversion 它檢查被校驗字段在類型轉換過程中是否出現錯誤。它可以接受如下兩個參數。

fieldname : 該參數指定校驗的Action屬性名,如果採用字段校驗器風格,則無需指定該參數。

repopulateField: 該參數指定當類型轉換失敗後,返回input頁面時,類型轉換失敗的表單域是否保留原來的錯誤輸入。

非字段風格:

<validators>

  <validator type=”conversion”>

<param name=”fieldName”>age</param>

<param name=”repopulateField”>false</param>

<message> 你的年齡必須是一個整數</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”age”>

<field-validator type=”conversion”>

<param name=”repopulateField”>true</param>

<message>你的年齡必須是一個整數</message>

</field-validator>

  </field>

</validators>

字符串長度校驗器  stringlength  它要求被校驗字段的長度必須在指定的範圍之內,否則就算校驗失敗。可接受如下幾個參數

fieldname : 該參數指定Action屬性名,如果採用非字段校驗器風格,則無需指定。

maxLength: 最大長度。

minLength: 最小長度。

trim: 指定校驗該字段之前是否截斷該字段值前後的空白。

非字段風格:

<validators>

  <validator type=”stringlength”>

<param name=”fieldName”>user</param>

<param name=”minLength”>4</param>

<param name=”maxLength”>20</param>

<message> 你的用戶名長度必須在4到20之間</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”user”>

<field-validator type=”stringlength”>

<param name=”minLength”>4</param>

<param name=”maxLength”>20</param>

<message>你的用戶名長度必須在4到20之間</message>

</field-validator>

  </field>

</validators>

正則表達式校驗器 regex 它檢查被校驗字段是否匹配一個正則表達式。該校驗器可接受如下幾個參數

fieldname: 指定校驗Action的屬性名,如果採用字段校驗器風格,則無需指定該參數。

expression: 該參數是必填的,該參數指定匹配用的正則表達式。

caseSensitive: 該參數指明進行正則表達式匹配時,是否區分大小寫,默認是true,可選。

非字段風格:

<validators>

  <validator type=”regex”>

<param name=”fieldName”>user</param>

<param name=”expression”><![CDATA[(\w{4,20})]]></param>

<message> 你的用戶名長度必須在4到20之間,且必須爲字母或數字</message>

  </validator>

</validators>

字段校驗配置風格

<validators>

  <field name=”user”>

<field-validator type=”regex”>

<param name=”expression”><![CDATA[(\w{4,20})]]></param>

<message> 你的用戶名長度必須在4到20之間,且必須爲字母或數字</message>

</field-validator>

  </field>

</validators>

基於Annotation的輸入校驗

使用驗證器Annotation 指定驗證規則修改時Action裏各屬性的settter方法。

@RequiredStringValidator(key=”name.requried”,message=””)
public void setName(String name){
…
}

手動完成輸入校驗

重寫validate()方法,通過重寫ActionSupport類的validate()方法來校驗。

public void validate()
	{
		System.out.println("進入validate方法進行校驗"
			+ name);
		//要求用戶名必須包含crazyit子串
		if(!name.contains("crazyit"))
		{
			addFieldError("user" , 
				"您的用戶名必須包含crazyit!");
		}
}

重寫validateXxx()方法,如果我們只想校驗Action的某個處理邏輯,僅校驗某個處理方法,則重寫validate方法是不夠的,validate()方法無法準確知道需要校驗那個處理方法。實際上,重寫validate方法會校驗所有的處理邏輯。爲了實現校驗指定處理邏輯的功能,Struts2的Action允許提供一個validateXxx()方法,xxx對應Action對應的處理邏輯方法。


































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