《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第6章_第1頁(yè)
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第6章_第2頁(yè)
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第6章_第3頁(yè)
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第6章_第4頁(yè)
《基于JavaEE的電子商務(wù)網(wǎng)站建設(shè)》課件第6章_第5頁(yè)
已閱讀5頁(yè),還剩158頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第6章Struts2類(lèi)型轉(zhuǎn)換與數(shù)據(jù)驗(yàn)證6.1注冊(cè)功能的初步實(shí)現(xiàn)6.2Struts2的數(shù)據(jù)類(lèi)型轉(zhuǎn)換6.3Struts2的數(shù)據(jù)驗(yàn)證

6.1注冊(cè)功能的初步實(shí)現(xiàn)

1.注冊(cè)頁(yè)面和提交成功頁(yè)面

以下Struts2標(biāo)簽實(shí)現(xiàn)注冊(cè)表單提交和顯示功能。注冊(cè)信息包括六個(gè)表單域:用戶(hù)名(username)、密碼(password)、重復(fù)密碼(repassword)、年齡(age)、出生年月(birthday)、電子郵件字段(email)。新建register.jsp文件,注意文件的放置目錄為ch05/WebRoot。代碼如下:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="GB2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

<body>

<s:formaction="registerAction">

<s:textfieldname="username"

label="username"></s:textfield><s:passwordname="password"label="password"></s:password>

<s:passwordname="repassword"label="repassword"></s:password>

<s:textfieldname="age"label="age"></s:textfield>

<s:textfieldname="birthday"label="birthday"></s:textfield>

<s:textfieldname="email"label="email"></s:textfield>

<s:submitname="submit"></s:submit>

</s:form>

</body>新建registerok.jsp,代碼如下

<%@pagelanguage="java"import="java.util.*"pageEncoding="GB2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

<body>

username:<s:propertyvalue="username"/><br/>

password:<s:propertyvalue="password"/><br/>

age:<s:propertyvalue="age"/><br/>

birthday:<s:propertyvalue="birthday"/><br/>

email:<s:propertyvalue="email"/><br/>

</body>以上兩個(gè)文件的運(yùn)行界面分別如圖6-1和圖6-2所示。由于尚未配置Struts2控制器,注冊(cè)響應(yīng)界面無(wú)值傳入,所以運(yùn)行界面如圖6-2所示。

圖6-1注冊(cè)表單頁(yè)面圖6-2注冊(cè)響應(yīng)頁(yè)面

2.?RegisterAction控制器類(lèi)的完成

【步驟1】建立控制器類(lèi)com.action.RegisterAction.java。

在ch05工程的src目錄下,右鍵單擊【New】的【Class】子菜單,在打開(kāi)的如圖6-3所示的頁(yè)面中填寫(xiě)相關(guān)信息,新建com.action包中的Action文件RegisterAction.java,并繼承ActionSupport類(lèi)。圖6-3新建控制器類(lèi)

【步驟2】完成RegisterAction.java代碼。

在新建的RegisterAction.java文件中完成如下代碼:

packagecom.action;

importjava.util.Date;

importcom.opensymphony.xwork2.ActionSupport;

publicclassRegisterActionextendsActionSupport{

privateStringusername;

privateStringpassword;

privateStringrepassword;

privateintage;

privateDatebirthday;

privateStringemail;

publicStringgetUsername(){

returnusername;}

publicvoidsetUsername(Stringusername){

this.username=username;}

publicStringgetPassword(){

returnpassword;}

publicvoidsetPassword(Stringpassword){

this.password=password;}

publicStringgetRepassword(){

returnrepassword;}

publicvoidsetRepassword(Stringrepassword){

this.repassword=repassword;}

publicintgetAge(){

returnage;}

publicvoidsetAge(intage){

this.age=age;}

publicDategetBirthday(){

returnbirthday;}

publicvoidsetBirthday(Datebirthday){

this.birthday=birthday;}

publicStringgetEmail(){

returnemail;}

publicvoidsetEmail(Stringemail){

this.email=email;}

publicStringexecute()throwsException{

returnSUCCESS;

}

}

3.?struts.xml的配置

打開(kāi)第5章建立的struts.xml文件,在package標(biāo)簽中添加以下代碼:

<actionname="registerAction"

class="com.action.RegisterAction">

<resultname="input">/register.jsp</result>

<resultname="success">/registerok.jsp</result>

</action>

4.運(yùn)行結(jié)果

完成配置后可以運(yùn)行本項(xiàng)目。部署好后,啟動(dòng)服務(wù)器,在IE中輸入地址http://localhost/ch05/register.jsp,將顯示如圖6-4所示的界面,填好信息后點(diǎn)擊【Submit】按鈕,即可進(jìn)入圖6-5所示的界面。注意,此時(shí)地址欄的名字為http://localhost/ch05/registerAction.action,但界面內(nèi)容卻是registerok.jsp,說(shuō)明struts.xml配置成功。圖6-4運(yùn)行輸入界面圖6-5提交轉(zhuǎn)入頁(yè)面6.2Struts2的數(shù)據(jù)類(lèi)型轉(zhuǎn)換

6.2.1Struts2中數(shù)據(jù)類(lèi)型轉(zhuǎn)換的處理

1.內(nèi)置的類(lèi)型轉(zhuǎn)換器

Struts2內(nèi)置的類(lèi)型轉(zhuǎn)換器支持大多數(shù)常用數(shù)據(jù)類(lèi)型的轉(zhuǎn)換,因此,這些類(lèi)型在開(kāi)發(fā)過(guò)程中不用處理類(lèi)型轉(zhuǎn)換。如6.1節(jié)中RegisterAction.java中的age和birthday都不是String類(lèi)型,但系統(tǒng)都會(huì)對(duì)它們自動(dòng)轉(zhuǎn)換類(lèi)型。

Struts2內(nèi)置的類(lèi)型轉(zhuǎn)換器可以處理以下類(lèi)型:

●布爾型:boolean/Boolean;

●字符型:char/Character;

●數(shù)值型:int/Integer、long/Long、float/Float、double/Double;

●日期型:Date,采用用戶(hù)請(qǐng)求所在Locale的SHORT格式處理;

●數(shù)組:array,按具體數(shù)組元素轉(zhuǎn)換;

●集合:collection,默認(rèn)集合元素為String類(lèi)型,把所有字符串封裝在ArrayList中。

2.?OGNL機(jī)制

Struts2借助OGNL表達(dá)式的支持,允許將參數(shù)轉(zhuǎn)換成復(fù)合類(lèi)型對(duì)象。

舉例,把6.1節(jié)的注冊(cè)代碼重寫(xiě)如下:

【步驟1】視圖界面。

register1.jsp代碼:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="GB2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

……<body>

<s:formaction="registerAction1">

<s:textfieldname="user.username"label="username"></s:textfield>

<s:passwordname="user.password"label="password"></s:password>

<s:passwordname="user.repassword"label="repassword"></s:password>

<s:textfieldname="user.age"label="age"></s:textfield>

<s:textfieldname="user.birthday"label="birthday"></s:textfield><s:textfieldname="user.email"label="email"></s:textfield>

<s:submitname="submit"></s:submit>

</s:form>

</body>

registerok1.jsp代碼:

<%@pagelanguage="java"import="java.util.*"pageEncoding="GB2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

……

<body>

username:<s:propertyvalue="user.username"

/><br/>

password:<s:propertyvalue="user.password"/><br/>

age:<s:propertyvalue="user.age”/><br/>

birthday:<s:propertyvalue="user.birthday"/><br/>

email:<s:propertyvalue="user.email"/><br/>

</body>

【步驟2】完成action。

com.bean.User.java代碼:

packagecom.bean;

importjava.util.Date;

publicclassUser{

privateStringusername;

privateStringpassword;

privateStringrepassword;

privateintage;

privateDatebirthday;

privateStringemail;

//省略get/set方法

}

com.action.RegisterAction1.java代碼:

packagecom.action;

importcom.bean.User;

importcom.opensymphony.xwork2.ActionSupport;

publicclassRegisterAction1extendsActionSupport{

privateUseruser;

publicUsergetUser(){

returnuser;}

publicvoidsetUser(Useruser){

this.user=user;}

publicStringexecute()throwsException{

returnSUCCESS;

}

}

【步驟3】struts.xml配置。

增加如下代碼:

<actionname="registerAction1"

class="com.action.RegisterAction1">

<resultname="input">/register1.jsp</result>

<resultname="success">/registerok1.jsp</result>

</action>在以上示例中,把所有注冊(cè)屬性都封裝到了User.java類(lèi)中,而在RegisterAction1.java中把User對(duì)象類(lèi)型作為屬性類(lèi)型。對(duì)于這樣的對(duì)象類(lèi)型轉(zhuǎn)換,Struts2提供的OGNL表達(dá)式允許開(kāi)發(fā)者無(wú)需任何特殊處理就可以轉(zhuǎn)換,只要像register1.jsp和registerok1.jsp代碼中的黑體部分那樣,在定義表單域時(shí)使用合法的OGNL表達(dá)式即可,如、user.age。

3.集合的轉(zhuǎn)換

為了讓Struts2了解集合屬性中元素的類(lèi)型,有以下兩種方式可以使用:

●使用泛型技術(shù)來(lái)直接指定集合元素類(lèi)型(推薦使用);

●通過(guò)Action的局部類(lèi)型轉(zhuǎn)換文件(詳見(jiàn)6.2.2節(jié))指定集合元素類(lèi)型。

這部分內(nèi)容將在下節(jié)詳述,可以將email改變?yōu)閾碛卸鄠€(gè)值的集合的處理。6.2.2自定義的類(lèi)型轉(zhuǎn)換器

如果內(nèi)置的類(lèi)型轉(zhuǎn)換器不能滿(mǎn)足用戶(hù)的Web應(yīng)用需求,那么Struts2也提供了自己開(kāi)發(fā)類(lèi)型轉(zhuǎn)換器的方法。而要?jiǎng)?chuàng)建一個(gè)類(lèi)型轉(zhuǎn)換器,則需實(shí)現(xiàn)ognl.TypeConverter接口,但該接口中的方法convertValue()太復(fù)雜。

org.apache.struts2.util.StrutsTypeConverter抽象類(lèi)中提供了兩個(gè)抽象方法用于字符串和其他類(lèi)型的相互轉(zhuǎn)換。這兩個(gè)方法如下:●?convertFromString(Maparg0,String[]arg1,Classarg2):從字符串轉(zhuǎn)換為指定對(duì)象類(lèi)型,即把客戶(hù)端獲得的字符串?dāng)?shù)據(jù)轉(zhuǎn)化成服務(wù)器需要的數(shù)據(jù)類(lèi)型。arg0表示action上下文的Map對(duì)象;arg1是要轉(zhuǎn)換的字符串值;arg2是要轉(zhuǎn)換的目標(biāo)類(lèi)型。

●?convertToString(Maparg0,Objectarg1):將指定對(duì)象轉(zhuǎn)換為字符串,即把服務(wù)器處理好的實(shí)際結(jié)果數(shù)據(jù)類(lèi)型轉(zhuǎn)換成客戶(hù)端輸出顯示的字符串?dāng)?shù)據(jù)。arg0表示action上下文的Map對(duì)象;arg1是要轉(zhuǎn)換的對(duì)象。下面我們對(duì)注冊(cè)的action屬性進(jìn)行重新設(shè)置,改變的要求如下:

(1)?birthday屬性:輸入的字符串提交后轉(zhuǎn)換為"yyyy-MM-dd"的日期格式;

(2)?email屬性:可以輸入以分號(hào)(;)隔開(kāi)的多個(gè)email值,用List集合來(lái)保存,輸出顯示[第1個(gè)Email為:aa@163.com,第2個(gè)Email為:bb@163.com,第3個(gè)Email為:cc@163.com]等不定個(gè)數(shù)的email值格式。

【步驟1】修改com.action.RegisterAction.java類(lèi)。

由于email要修改為L(zhǎng)ist集合保存的多個(gè)值,因此要在RegisterAction.java中把原來(lái)的代碼:

privateStringemail;

publicStringgetEmail(){

returnemail;

}

publicvoidsetEmail(Stringemail){

this.email=email;

}修改為如下代碼來(lái)滿(mǎn)足需求:

privateList<String>email;

publicList<String>getEmail(){

returnemail;

}

publicvoidsetEmail(List<String>email){

this.email=email;

}

【步驟2】編寫(xiě)日期類(lèi)型轉(zhuǎn)換器。

要滿(mǎn)足顯示"yyyy-MM-dd"日期格式,需編寫(xiě)日期類(lèi)型轉(zhuǎn)換器com.converter.DateConverter.java,代碼如下:

packagecom.converter;

importjava.text.ParseException;

importjava.text.SimpleDateFormat;

importjava.util.Map;

importorg.apache.struts2.util.StrutsTypeConverter;

import

com.opensymphony.xwork2.util.TypeConversionException;

publicclassDateConverterextendsStrutsTypeConverter{

privatestaticSimpleDateFormatsf=newSimpleDateFormat("yyyy-MM-dd");

//客戶(hù)端到服務(wù)器端

publicObjectconvertFromString(Maparg0,String[]arg1,Classarg2)

{try

{//將取得的客戶(hù)端輸入數(shù)據(jù)放入str;

String[]str=(String[])arg1;

//使用“yyyy-MM-dd”日期格式解析字符串值,返回Date對(duì)象

returnsf.parse(str[0]);

}

catch(ParseExceptione)

{thrownewTypeConversionException(

e.getMessage()+"["+arg1+"-class:"+arg2+"]");

}

}

//服務(wù)器端到客戶(hù)端

publicStringconvertToString(Maparg0,Objectarg1)

{

//使用"yyyy-MM-dd"日期格式格式化Date對(duì)象,

返回字符串

returnsf.format(arg1);

}

}

【步驟3】編寫(xiě)email類(lèi)型轉(zhuǎn)換器。

email屬性的變化較大,請(qǐng)讀者注意此轉(zhuǎn)換器的代碼中對(duì)集合的處理部分的代碼。email類(lèi)型轉(zhuǎn)換器com.converter.EmailConverter.java的代碼如下:

packagecom.converter;

importjava.util.ArrayList;

importjava.util.List;

importjava.util.Map;

importorg.apache.struts2.util.StrutsTypeConverter;

publicclassEmailConverterextendsStrutsTypeConverter{

//客戶(hù)端到服務(wù)器端

publicObjectconvertFromString(Maparg0,String[]arg1,Classarg2){

List<String>list=newArrayList<String>();

String[]str=(String[])arg1;

//分隔分號(hào)中的數(shù)據(jù)存入數(shù)組paramValues;

String[]paramValues=str[0].split(";");

//遍歷數(shù)組paramValues,把數(shù)字元素存入集合list

for(Stringparam:paramValues){

list.add(param);

}

returnlist;

}

//服務(wù)器端到客戶(hù)端

publicStringconvertToString(Maparg0,Objectarg1){

//取出處理后的數(shù)據(jù),轉(zhuǎn)化為集合類(lèi)型;

List<String>emails=(List<String>)arg1;

Stringresult="[";

inti=0;

//遍歷集合設(shè)置輸出字符串內(nèi)容

for(Stringemail:emails){

i++;

result+="第"+i+"個(gè)Email為:"+email+",";

}

//把最后一個(gè)逗號(hào)去掉

result=result.substring(0,result.length()-1);

result+="]";

returnresult;

}

}

【步驟4】注冊(cè)類(lèi)型轉(zhuǎn)換器。

僅僅為該應(yīng)用提供類(lèi)型轉(zhuǎn)換器還不夠,因?yàn)镾truts2依然不知道何時(shí)使用這些類(lèi)型轉(zhuǎn)換器,因此要對(duì)寫(xiě)好的類(lèi)型轉(zhuǎn)換器進(jìn)行注冊(cè),讓Struts2框架知道它們的存在。

Struts2支持以下三種注冊(cè)類(lèi)型轉(zhuǎn)換器的方式:

●局部類(lèi)型轉(zhuǎn)換器;

●全部類(lèi)型轉(zhuǎn)換器;

●使用Struts2提供的類(lèi)型轉(zhuǎn)換注解來(lái)配置。

(1)應(yīng)用于局部的類(lèi)型轉(zhuǎn)換器。

要指定局部范圍的類(lèi)型轉(zhuǎn)換器,需要建立屬性文件RegisterAperties。此文件名中后半部分(-perties)名字固定,前半部分(RegisterAction)為屬性文件中所定義的屬性所在的Action文件名。

選中com.action包,用右鍵【New】選中【File】,在打開(kāi)的如圖6-6所示的頁(yè)面中輸入文件名RegisterAperties,點(diǎn)擊【Finish】按鈕。圖6-6新建屬性文件在新建屬性文件的【Source】視圖中輸入以下代碼,可完成局部轉(zhuǎn)換器的注冊(cè)。

birthday=com.converter.DateConverter

email=com.converter.EmailConverter

從代碼中可以歸納出局部屬性文件的兩個(gè)特點(diǎn):

●每個(gè)屬性定義遵循的格式為:要轉(zhuǎn)換的類(lèi)屬性名=類(lèi)型轉(zhuǎn)換器的類(lèi)文件全稱(chēng);

●定義多個(gè)要轉(zhuǎn)換的屬性時(shí),只需分行定義,不能用標(biāo)點(diǎn)隔開(kāi)。分析整個(gè)轉(zhuǎn)換過(guò)程:從register.jsp提交到RegisterAction.java,當(dāng)遇到setBirthday()方法時(shí),系統(tǒng)到對(duì)應(yīng)的屬性文件RegisterAperties中檢查有無(wú)對(duì)此屬性進(jìn)行類(lèi)型轉(zhuǎn)換,如果有,則執(zhí)行屬性文件中對(duì)應(yīng)屬性轉(zhuǎn)換的類(lèi)DateConverter.java,然后檢查轉(zhuǎn)換的方向,是客戶(hù)端到服務(wù)器端還是服務(wù)器端到客戶(hù)端,此處是字符串到Date類(lèi)的轉(zhuǎn)換,即選擇convertFromString()方法,把處理后的結(jié)果返回Date類(lèi)值賦給setBirthday()中的birthday。這樣便完成了注冊(cè)提交數(shù)據(jù)的轉(zhuǎn)換過(guò)程。

(2)應(yīng)用于全局的類(lèi)型轉(zhuǎn)換器。

注冊(cè)全局類(lèi)型轉(zhuǎn)換器,可以使得注冊(cè)的類(lèi)型在所有的Action執(zhí)行時(shí)都起作用。

全局類(lèi)型轉(zhuǎn)換注冊(cè)文件應(yīng)該放在WEB-INF/classes文件夾根目錄中,和struts.xml在同一目錄,其文件名是perties,此文件名不可更改。由于也是.properties文件,其創(chuàng)建方式見(jiàn)圖6-6,把文件放在ch05/src根目錄,配置代碼如下:

java.util.Date=com.converter.DateConverter由于email屬性的轉(zhuǎn)換器具有特殊性,因此不在全局文件中配置。注意,此時(shí)要把局部文件中birthday配置注釋掉,否則全局轉(zhuǎn)換器不起作用,因?yàn)榫植孔?cè)文件會(huì)覆蓋全局文件中相同的內(nèi)容。

屬性文件的注釋方式就是在語(yǔ)句前加井(#)號(hào),代碼

如下:

#birthday=com.converter.DateConverter

【步驟5】運(yùn)行結(jié)果。

通過(guò)以上4個(gè)步驟的處理,基本完成了本實(shí)例對(duì)birthday和email的需求。注意,本實(shí)例是在6.1節(jié)實(shí)例的基礎(chǔ)上做的修改,已有的文件不重復(fù)講述。重啟Tomcat,運(yùn)行工程路徑http://localhost/ch05/register.jsp,如圖6-7所示,提交結(jié)果如圖6-8所示。圖6-7提交輸入頁(yè)面圖6-8提交轉(zhuǎn)換頁(yè)面6.2.3類(lèi)型轉(zhuǎn)換錯(cuò)誤的處理

圖6-7中輸入的數(shù)據(jù)都是人為的,難免會(huì)發(fā)生輸入格式不正確的情況,如在age中輸入abc,在birthday中輸入2001/1/1,在email中輸入aa@163.com,bb@163.com等。圖6-9顯示了進(jìn)行以上輸入后的執(zhí)行界面。圖6-9類(lèi)型轉(zhuǎn)換錯(cuò)誤提示頁(yè)面1

1.類(lèi)型轉(zhuǎn)換的錯(cuò)誤提示

從圖6-9看到,age和birthday由于數(shù)據(jù)類(lèi)型錯(cuò)誤而出現(xiàn)“Invalidfieldvalueforfield‘a(chǎn)ge’”的提示,email雖然轉(zhuǎn)換了但并不是我們想要的結(jié)果。在這里涉及了兩方面的處理:數(shù)據(jù)校驗(yàn)(email)和類(lèi)型轉(zhuǎn)換(age)。就像email的錯(cuò)誤那樣,輸入的數(shù)據(jù)可以進(jìn)行有效轉(zhuǎn)換,但轉(zhuǎn)換的結(jié)果依然是非法數(shù)據(jù)。所以,數(shù)據(jù)驗(yàn)證的前提還是類(lèi)型轉(zhuǎn)換,只有轉(zhuǎn)換為正確的數(shù)據(jù)才能對(duì)此數(shù)據(jù)進(jìn)行處理驗(yàn)證。圖中,age、birthday的類(lèi)型轉(zhuǎn)換錯(cuò)誤我們并沒(méi)有定義過(guò),那么它們的錯(cuò)誤提示來(lái)自哪里?當(dāng)發(fā)生類(lèi)型轉(zhuǎn)換錯(cuò)誤時(shí),Struts2會(huì)調(diào)用conversionError的攔截器,這在defaultStack默認(rèn)攔截器棧中定義。處于struts-default.xml文件中的相關(guān)代碼如下(具體見(jiàn)6.4節(jié)):

<interceptor-stackname=“defaultStack”>

……

<!--處理類(lèi)型轉(zhuǎn)換攔截器-->

<interceptor-refname="conversionError"/>

<!--處理數(shù)據(jù)校驗(yàn)攔截器-->

<interceptor-refname="validation">

<param

name="excludeMethods">

input,back,cancel,browse</param>

</interceptor-ref>

……

</interceptor-stack>然后將對(duì)應(yīng)錯(cuò)誤封裝成表單域錯(cuò)誤(FieldError),并將這些錯(cuò)誤信息放入ActionContext中,然后系統(tǒng)會(huì)跳轉(zhuǎn)到名為input的邏輯視圖中。

因此歸納提示用戶(hù)類(lèi)型轉(zhuǎn)換錯(cuò)誤有三個(gè)必要條件:

●引用defaultStack攔截器棧(一般action配置中默認(rèn)配置,特殊情況請(qǐng)見(jiàn)6.4節(jié));

●讓Action類(lèi)繼承ActionSupport類(lèi);

●為Action配置添加input映射。

2.錯(cuò)誤提示的位置

在圖6-9中,對(duì)于age和birthday的錯(cuò)誤提示分別在它們所在的表單組件的上方,而且表單中還會(huì)保留錯(cuò)誤的輸入內(nèi)容,這些都是Struts2中表單標(biāo)簽自帶的功能,可以自動(dòng)輸出與其關(guān)聯(lián)的錯(cuò)誤信息,通過(guò)字段名來(lái)關(guān)聯(lián)。

如果我們想改變信息提示的位置,讓它們更醒目一些,該怎么做?主要是對(duì)fielderror標(biāo)簽和表單主題進(jìn)行處理。前面已經(jīng)提到錯(cuò)誤內(nèi)容被封裝成表單域錯(cuò)誤(FieldError),那么可以使用fielderror標(biāo)簽來(lái)訪(fǎng)問(wèn)錯(cuò)誤,修改register.jsp頁(yè)面,添加代碼在body標(biāo)簽的第一句如下:

<s:fielderrorcssStyle="color:red"/>

則重新運(yùn)行錯(cuò)誤的類(lèi)型輸入提交,所有的錯(cuò)誤提示將集中顯示在頁(yè)頭,而且用紅色標(biāo)注,一目了然,如圖6-10所示。圖6-10類(lèi)型轉(zhuǎn)換錯(cuò)誤提示頁(yè)面2但是圖6-10中仍然有明顯的缺陷,就是表單域中的提示還在,這是因?yàn)檫@里的表單使用了xhtml主題的表單標(biāo)簽。我們可以再做以下修改,使得錯(cuò)誤提示頁(yè)面顯示為圖6-11

所示。圖6-11類(lèi)型轉(zhuǎn)換錯(cuò)誤提示頁(yè)面3

【步驟1】新建提交頁(yè)面。

要完成以上轉(zhuǎn)變,需在實(shí)例中做如下修改,新建register_simple.jsp來(lái)完成原來(lái)register.jsp的頁(yè)面,代碼如下:

<%@pagelanguage="java"import="java.util.*"

pageEncoding="gb2312"%>

<%@taglibprefix="s"uri="/struts-tags"%>

<body>

<s:formaction="simpleRegisterAction.action"

theme="simple">

<tablewidth="70%"border="1">

<tr><td>username</td>

<td><s:textfieldname="username"

label="username"></s:textfield></td>

<td><s:fielderrorcssStyle="color:red">

<s:param>username</s:param>

</s:fielderror>

</td></tr>

<tr><td>password</td>

<td><s:passwordname="password"

label="password"></s:password></td>

<td><s:fielderrorcssStyle="color:red">

<s:param>password</s:param>

</s:fielderror>

</td></tr>

<tr><td>re-password</td>

<td><s:passwordname="repassword"

label="repassword"></s:password></td>

<td><s:fielderrorcssStyle="color:red">

<s:param>repassword</s:param>

</s:fielderror>

</td></tr>

<tr><td>age</td>

<td><s:textfieldname="age"label=“age”>

</s:textfield></td>

<td><s:fielderrorcssStyle="

color:red"

>

<s:param>age</s:param>

</s:fielderror>

</td></tr>

<tr><td>birthday</td>

<td><s:textfieldname=“birthday”label="birthday">

</s:textfield></td>

<td><s:fielderrorcssStyle="color:red">

<s:param>birthday</s:param>

</s:fielderror>

</td></tr>

<tr><td>email</td>

<td><s:textfieldname"email"

label="email">

</s:textfield></td>

<td><s:fielderrorcssStyle="color:red">

<s:param>email</s:param>

</s:fielderror>

</td></tr>

<tr><td><s:submitvalue="submit"></s:submit></td>

<td><s:resetvalue="reset"></s:reset></td>

</tr></table></s:form>

</body>

【步驟2】修改Action文件。

為了6.3節(jié)和6.4節(jié)中的一些應(yīng)用,我們?cè)赗egisterAction.java中增加一個(gè)與execute方法結(jié)構(gòu)一樣的方法simple(),代碼如下:

publicStringsimple()throwsException{

System.out.println("abcexecute...");

returnSUCCESS;

}

【步驟3】配置struts.xml。

在struts.xml中對(duì)simpleRegisterAction.action進(jìn)行配置,代碼如下:

<actionname="simpleRegisterAction"

class="com.action.RegisterAction”method="simple"

>

<resultname="input">/register_simple.jsp</result>

<resultname="success">/registerok.jsp</result>

3.錯(cuò)誤提示內(nèi)容

在默認(rèn)的情況下,所有的轉(zhuǎn)換錯(cuò)誤都使用通用的i18n消息鍵來(lái)報(bào)告錯(cuò)誤,我們可以改變這些消息鍵來(lái)達(dá)到目的。一般的做法如下:

【步驟1】定義全局屬性文件名。

在struts.xml文件中已經(jīng)定義了語(yǔ)句,如果沒(méi)有,請(qǐng)加上:

<constantname="struts.custom.i18n.resources"

value="message"></constant>其中:constant標(biāo)簽表示在所有框架中使用的常量,這些常量會(huì)替代struts中內(nèi)置的相應(yīng)常量;name是常量名;struts.custom.i18n.resources是struts中國(guó)際化的資源文件,用來(lái)定義自動(dòng)產(chǎn)生的信息;value屬性定義資源文件的名字,此處表示對(duì)應(yīng)的文件是建立在WEB-INF/classes根目錄下的perties文件。

【步驟2】完善全局屬性文件。

錯(cuò)誤提示屬性文件的編寫(xiě)內(nèi)容可以針對(duì)所有的屬性,也可以針對(duì)個(gè)別屬性,一般建議在全局屬性文件中定義的內(nèi)容是針對(duì)所有的屬性。如果在perties文件中輸入代碼,那么任何錯(cuò)誤都將提示“屬性名invalid”:

xwork.default.invalid.fieldvalue={0}invalid

在輸出類(lèi)型錯(cuò)誤消息時(shí),占位符{0}將自動(dòng)被字段名所代替,如圖6-12所示。圖6-12類(lèi)型轉(zhuǎn)換錯(cuò)誤提示頁(yè)面3

【步驟3】完善局部屬性文件。

我們還可以通過(guò)建立局部屬性文件來(lái)處理特定字段的特殊提示。Struts2規(guī)定局部屬性文件名與驗(yàn)證的Action名相同,如此處應(yīng)命名為RegisterAperties,并且此局部屬性文件必須建立在與驗(yàn)證的Action同一目錄下,即建立在com.action包中。代碼如下:

invalid.fieldvalue.birthday=birthdaysformatisyyyy-MM-DD!左邊為invalid.fieldvalue.+錯(cuò)誤屬性字段名,右邊為顯示的內(nèi)容,因此運(yùn)行后的界面如圖6-13所示。圖6-13類(lèi)型轉(zhuǎn)換錯(cuò)誤提示頁(yè)面4

6.3Struts2的數(shù)據(jù)驗(yàn)證

對(duì)用戶(hù)輸入數(shù)據(jù)進(jìn)行驗(yàn)證包括客戶(hù)端驗(yàn)證和服務(wù)器端驗(yàn)證??蛻?hù)端驗(yàn)證主要通過(guò)JavaScript腳本代碼來(lái)實(shí)現(xiàn)有效的數(shù)據(jù)格式,為服務(wù)器端過(guò)濾數(shù)據(jù);而服務(wù)器端驗(yàn)證除了可以再次驗(yàn)證數(shù)據(jù)格式外,還可以進(jìn)行數(shù)據(jù)邏輯的驗(yàn)證,如年齡是否符合規(guī)定等。那么讀者會(huì)提出疑問(wèn),數(shù)據(jù)格式到底是在客戶(hù)端還是服務(wù)器端驗(yàn)證,還是二者皆要?一般構(gòu)建Web應(yīng)用時(shí)通常要先在客戶(hù)端進(jìn)行表單數(shù)據(jù)格式驗(yàn)證,減少服務(wù)器負(fù)載。但是由于JavaScript腳本可以在客戶(hù)端被屏蔽掉,或有高手可以直接通過(guò)Socket通信來(lái)向服務(wù)器端直接傳送非法數(shù)據(jù)攻擊系統(tǒng),因此最好在服務(wù)器端進(jìn)行重復(fù)數(shù)據(jù)有效性驗(yàn)證。對(duì)于服務(wù)器端驗(yàn)證,Struts2提供了三種方式:

●使用Action中的validate()方法驗(yàn)證數(shù)據(jù);

●使用驗(yàn)證框架;

●使用驗(yàn)證注解。6.3.1編寫(xiě)Java代碼并驗(yàn)證

ActionSupport抽象類(lèi)中提供了一個(gè)validate()方法來(lái)存放校驗(yàn)代碼,只有通過(guò)了validate()中的驗(yàn)證,Action才會(huì)執(zhí)行execute()方法。

1.?Field錯(cuò)誤信息

【步驟1】修改Action文件。

對(duì)LoginAction.java的修改主要是修改繼承類(lèi)和增加validate()方法,代碼如下:

publicclassLoginActionextendsActionSupport{

……//省略不修改部分

publicvoidvalidate(){

if(null==username||username.trim().length()==0){

this.addFieldError("username","usernamemustnotbenull!");

}

if(username.length()<6||username.length()>10){

this.addFieldError("username","usernameinvalid");

}

if(null==password||password.trim().length()==0){

this.addFieldError("password","passwordmustnotbenull!");

}

if(password.length()<6||password.length()>10){

this.addFieldError("password","passwordinvalid");

}

}

addFieldError(參數(shù)1,參數(shù)2)方法中的參數(shù)1表示放入

域(Field)錯(cuò)誤中的對(duì)應(yīng)屬性的名字,參數(shù)2表示提示的錯(cuò)誤信息。此文件其實(shí)可以不修改,為了給用戶(hù)一個(gè)必填的提示,在表單組件中增加required屬性值為true,則在表單顯示頁(yè)面中該組件會(huì)標(biāo)注星號(hào)(*),代碼如下:

<body>

<s:fielderrorcssStyle="color:red"/>

<s:formaction="loginAction"

>

<s:textfieldname="username"label=“username"required="true"

></s:textfield>

<s:passwordname="password"label="password"required="true"

></s:password>

<s:submitname="submit"></s:submit>

</s:form>

</body>

【步驟3】運(yùn)行結(jié)果。

重啟服務(wù)器,輸入U(xiǎn)RL進(jìn)行訪(fǎng)問(wèn),如圖6-14所示,不填表單數(shù)據(jù)直接提交的顯示頁(yè)面為圖6-15。

在圖6-15中,錯(cuò)誤信息不只在fielderror標(biāo)簽中顯示,而且還在表單組件上方顯示,這顯然沒(méi)有必要。如何讓表單組件上方不顯示錯(cuò)誤提示呢?圖6-14星號(hào)登錄頁(yè)面

圖6-15提交驗(yàn)證頁(yè)面

2.?Action錯(cuò)誤信息

為了使錯(cuò)誤提示不重復(fù),下面舉例來(lái)完善程序。

【步驟1】修改Action文件。

對(duì)LoginAction.java的修改主要是把錯(cuò)誤放入Action級(jí)別的錯(cuò)誤信息中,代碼如下:

publicvoidvalidate(){

if(null==username||username.trim().length()==0){

this.addActionError("usernamemustnotbenull!");

}elseif(username.length()<6||username.length()>10){

this.addActionError("usernameinvalid");

}

if(null==password||password.trim().length()==0){

this.addActionError("passwordmustnotbenull!");

}elseif(password.length()<6||password.length()>10){

this.addActionError(“passwordinvalid”);

}

}

addActionError(參數(shù)1)方法中的參數(shù)1表示提示的錯(cuò)誤

信息。

【步驟2】修改login.jsp文件。

此文件只需把原來(lái)顯示fielderror的標(biāo)簽改為actionerro標(biāo)簽即可,代碼如下:

<s:actionerrorcssStyle=“color:red”/>

【步驟3】運(yùn)行結(jié)果。

重啟服務(wù)器,輸入U(xiǎn)RL進(jìn)行訪(fǎng)問(wèn),不填表單數(shù)據(jù)直接提交的顯示頁(yè)面如圖6-16所示。圖6-16Action級(jí)別的錯(cuò)誤提示

3.?validate()方法和validateXxx()方法

由于Struts2的Action類(lèi)里可以包含多個(gè)處理邏輯,就是定義了多個(gè)與execute()方法結(jié)構(gòu)相同的邏輯方法,而并不是每個(gè)邏輯方法都需要輸入校驗(yàn),如添加數(shù)據(jù)一般要輸入驗(yàn)證,但刪除數(shù)據(jù)就沒(méi)必要。按照編程習(xí)慣,對(duì)于同一個(gè)數(shù)據(jù)表的操作CRUD一般都放在一個(gè)Action中,如果僅定義validate()方法顯然不能滿(mǎn)足需求,因?yàn)関alidate()方法無(wú)法知道需要校驗(yàn)?zāi)膫€(gè)處理邏輯。

Struts2的Action還允許提供一個(gè)validateXxx()方法來(lái)實(shí)現(xiàn)校驗(yàn)指定處理邏輯的功能。

【步驟1】修改Action文件。

對(duì)LoginAction.java的修改主要是增加validateLogin()方法,只判斷空值,而且提示信息有別于validate()中的定義。代碼如下:

publicvoidvalidateLogin(){

if(null==username||username.trim().length()==0){

this.addActionError("usernameisnull!");

}

if(null==password||password.trim().length()==0){

this.addActionError("passwordisnull!");

}

}

【步驟2】修改login.jsp文件。

此文件表單用于將提交Action改成isUMAction.action,因?yàn)樵趕truts.xml中配置好此action請(qǐng)求后,可執(zhí)行l(wèi)ogin()邏輯方法。代碼如下:

<body>

<s:actionerrorcssStyle="color:red"/>

<s:formaction="isUMAction">

<s:textfieldname="username"label="username"

required="true"></s:textfield>

<s:passwordname="password"label=“password"required="true"></s:password>

<s:submitname="submit"></s:submit>

</s:form>

</body>

【步驟3】運(yùn)行結(jié)果。

重啟服務(wù)器,輸入U(xiǎn)RL進(jìn)行訪(fǎng)問(wèn),不填表單數(shù)據(jù)直接提交的顯示頁(yè)面如圖6-17所示。圖6-17validatXxx()錯(cuò)誤提示1因此,在程序中把validate()方法名字改為validateExecute(),則空值錯(cuò)誤提示就只有頭兩行的提示,如圖6-18所示。圖6-18validatXxx()錯(cuò)誤提示26.3.2使用驗(yàn)證框架

1.在注冊(cè)程序中使用驗(yàn)證框架

校驗(yàn)規(guī)則針對(duì)register.jsp的每個(gè)表單域應(yīng)滿(mǎn)足的規(guī)則為:

●?username:字符串,不為空,長(zhǎng)度為6~10位;

●?password和repassword:字符串,不為空,長(zhǎng)度為6~10位,并且二者相等。

●?age:必填,1~150的整數(shù);

●?birthday:必填,1990-01-01到2010-01-01之間的日期型。

【步驟1】建立校驗(yàn)文件。

在com.action包中新建文件RegisterAction-validation.xml,進(jìn)行校驗(yàn)規(guī)則配置,其代碼如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEvalidatorsPUBLIC"-//OpenSymphony

Group//XWorkValidator1.0.2//EN"

"/xwork/xwork-validator-1.0.2.dtd">

<validators>

<fieldname="username">①<!--必填字符串校驗(yàn)器

-->

<field-validatortype=“requiredstring”>

<!--可省,默認(rèn)為true

<paramname=“trim”>true</param>

-->

<message>usernameshouldnotbeblank!</message>

</field-validator>③

<!--字符串長(zhǎng)度校驗(yàn)器

-->

<field-validatortype="stringlength">

<paramname="minLength">6</param>

<paramname="maxLength">10</param>

<message>

usernameshouldbebetween${minLength}and

${maxLength}

</message>

</field-validator>

</field>

<fieldname="password">

<field-validatortype="requiredstring">

<message>passwordshouldnotbeblank!</message>

</field-validator>④

<!--正則表達(dá)式校驗(yàn)器

-->

<field-validatortype="regex">

<param

name="expression">

<![CDATA[(\w{6,10})]]></param>

<message>

passwordshouldbebetween6and10!

</message>

</field-validator>

</field>

<fieldname="repassword">

<field-validatortype="requiredstring">

<message>repasswordshouldnotbeblank!</message>

</field-validator>

<field-validatortype="stringlength">

<paramname="minLength">6</param>

<paramname="maxLength">10</param>

<message>

repasswordshouldbebetween${minLength}and

${maxLength}

</message>

</field-validator>⑤

<!--字段表達(dá)式校驗(yàn)器

-->

<field-validatortype="fieldexpression">

<param

name="expression">

repassword==password</param>

<message>repasswordshouldbethesamewith

pass!</message>

</field-validator>

</field>

<fieldname="age">⑥

<!--整數(shù)校驗(yàn)器

-->

<field-validatortype="int">

<paramname="min">1</param>

<paramname="max">150</param>

<message>ageshouldbebetween${min}and

${max}</message>

</field-validator>

</field>

<fieldname="birthday">②

<!--必填校驗(yàn)器

-->

<field-validatortype="required">

<message>birthdayshouldnotbeblank!</message>

</field-validator>⑦

<!--日期校驗(yàn)器

-->

<field-validatortype="date">

<paramname="min">1900-01-01</param>

<paramname="max">2010-01-01</param>

<message>

birthdayshouldbebetween${min}and${max}!

</message>

</field-validator>

</field>

</validators>

【步驟2】運(yùn)行程序。

重啟Tomcat,運(yùn)行http://localhost/ch05/register.jsp,不對(duì)任何表單組件執(zhí)行輸入操作,點(diǎn)擊提交后,將出現(xiàn)如圖6-19所示的提示。圖6-19驗(yàn)證框架空值提示1再次運(yùn)行http://localhost/ch05/register.jsp,在圖6-20中輸入相關(guān)內(nèi)容,其中密碼輸入兩次不同,age不是整型,birthday不在指定范圍內(nèi),點(diǎn)擊提交后,將出現(xiàn)如圖6-21所示的提示。圖6-20注冊(cè)輸入頁(yè)面

圖6-21驗(yàn)證框架錯(cuò)誤輸入值提示

2.驗(yàn)證文件的取名和保存位置

從以上實(shí)例大部分讀者可以猜出,此驗(yàn)證文件必須放在與所要驗(yàn)證的Action文件的同一目錄下,并且文件名為ActionName-validation.xml,其中ActionName為Action的文件名,-validation.xml為固定寫(xiě)法。所以實(shí)例中的驗(yàn)證文件為com.action.RegisterAction-validation.xml。但我們知道,在一個(gè)Action中有多個(gè)負(fù)責(zé)執(zhí)行邏輯操作的方法,對(duì)于不同的邏輯操作要使用不同的配置文件,其處理方式為:同樣在要處理的Action文件的相同目錄中建立文件ActionName-ActionAliasName-validation.xml,其中ActionName為Action的文件名,ActionAliasName為邏輯方法名,-validation.xml為固定寫(xiě)法。所以如果要對(duì)RegisterAction.java文件中的simple()方法建立驗(yàn)證文件,則應(yīng)取名為com.action.RegisterAction-simple-validation.xml。接下來(lái)我們用Struts2提供的另一種校驗(yàn)規(guī)則來(lái)實(shí)現(xiàn)com.action.RegisterAction-login-validation.xml,僅定義用戶(hù)名不為空和長(zhǎng)度6~10位的驗(yàn)證,完成的代碼如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEvalidatorsPUBLIC"-//OpenSymphony

Group//XWorkValidator1.0.2//EN"

"/xwork/xwork-

validator-1.0.2.dtd">

<validators>

<validatortype="requiredstring">

<paramname="fieldName">username</param>

<message>simpleusernameshouldnotbe

blank!</message>

</validator>

<validatortype="stringlength">

<paramname="fieldName">username</param>

<paramname="minLength">6</param>

<paramname="maxLength">10</param>

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論