代碼貼士
select標(biāo)簽用來(lái)實(shí)現(xiàn)下拉列表框,emptyOption屬性取值為true,表示第一個(gè)下拉列表項(xiàng)為空白,取值為false或省略該屬性,則不生成空白列表項(xiàng);list屬性則指定用來(lái)生成下拉列表項(xiàng)的數(shù)據(jù)源,若該數(shù)據(jù)源是一個(gè)Map對(duì)象,則默認(rèn)的會(huì)將該Map對(duì)象的key值作為列表項(xiàng)的值(在程序中使用),將value值作為列表項(xiàng)的標(biāo)簽(顯示給用戶);name 屬性指定了與表單的處理類中對(duì)應(yīng)的setXXX()與getXXX()方法。
fielderror標(biāo)簽用來(lái)輸出通過(guò)Action類的addFieldError()方法保存的信息,param標(biāo)簽則指定要輸出保存的哪條信息。如果要輸出保存的全部信息,可使用<s2:fielderror/>。“%{}”用來(lái)計(jì)算表達(dá)式,被計(jì)算的表達(dá)式寫在“{}”中,如<s2:property value="%{100+1}"/>,將輸出“101”,所以,代碼中為param標(biāo)簽的value屬性指定的是字符串值typeError,若寫為<s2:param value="typeError"/>,則此時(shí)的typeError相當(dāng)于一個(gè)頁(yè)面變量。例如:<s2:set name="myError" value="%{'typeError'}"/><s2:param value="myError"/>與<s2:param value="%{'typeError'}"/>實(shí)現(xiàn)的功能是相同的。
3.在InfoAction類中實(shí)現(xiàn)處理信息發(fā)布請(qǐng)求的方法
例程42中指定表單所觸發(fā)的請(qǐng)求為info_Add.action,根據(jù)例程34中cityinfo.xml文件的配置,表單將被提交到InfoAction類的Add()方法中進(jìn)行處理,在這之前需要進(jìn)行表單驗(yàn)證。下面先來(lái)創(chuàng)建驗(yàn)證表單的方法。
創(chuàng)建驗(yàn)證表單的validateAdd()方法。
在該方法中,首先獲取表單數(shù)據(jù),然后再依次進(jìn)行驗(yàn)證。首先驗(yàn)證用戶輸入是否為空,在都不為空的情況下,再來(lái)驗(yàn)證輸入的聯(lián)系電話和E-mail格式是否正確。在驗(yàn)證過(guò)程中,若驗(yàn)證失敗,則調(diào)用addFieldError()方法保存提示信息。validateAdd()方法的代碼如下:
例程43 代碼位置:光盤\TM\01\src\com\yxq\action\InfoAction.java
public void validateAdd(){
int type=infoSingle.getInfoType(); //獲取信息類別表單數(shù)據(jù)
String title=infoSingle.getInfoTitle(); //獲取信息標(biāo)題表單數(shù)據(jù)
String content=infoSingle.getInfoContent(); //獲取信息內(nèi)容表單數(shù)據(jù)
String phone=infoSingle.getInfoPhone(); //獲取聯(lián)系電話表單數(shù)據(jù)
String linkman=infoSingle.getInfoLinkman(); //獲取聯(lián)系人表單數(shù)據(jù)
String email=infoSingle.getInfoEmail(); //獲取E-mail地址表單數(shù)據(jù)
boolean mark=true;
if(type<=0){
mark=false;
addFieldError("typeError",getText("city.info.no.infoType")); //getText(String key)方法用來(lái)獲取properties
資源文件中key指定的鍵值存儲(chǔ)的內(nèi)容
}
……//省略了其他表單數(shù)據(jù)的驗(yàn)證
if(mark){ //若表單數(shù)據(jù)都不為空
……//省略了驗(yàn)證聯(lián)系電話和E-mail格式的代碼
}
}
創(chuàng)建處理請(qǐng)求的Add()方法。
表單驗(yàn)證成功后,調(diào)用Add()方法處理請(qǐng)求。在該方法中先獲取表單數(shù)據(jù),然后生成SQL語(yǔ)句,最后調(diào)用OpDB類對(duì)象的OpUpdate()方法向數(shù)據(jù)表中插入記錄,完成信息發(fā)布。Add()方法的代碼如下:
例程44 代碼位置:光盤\TM\01\src\com\yxq\action\InfoAction.java
public String Add(){
String addType=request.getParameter("addType"); //獲取訪問(wèn)該方法的請(qǐng)求要進(jìn)行的操作
if(addType==null||addType.equals("")){
request.setAttribute("mainPage","/pages/add/addInfo.jsp");
addType="linkTo";
}
if(addType.equals("add")){ //執(zhí)行信息發(fā)布操作
request.setAttribute("mainPage","/pages/error.jsp");
OpDB myOp=new OpDB();
Integer type=Integer.valueOf(infoSingle.getInfoType()); //獲取信息類別
String title=infoSingle.getInfoTitle(); //獲取信息標(biāo)題
String content=DoString.HTMLChange(infoSingle.getInfoContent()); //轉(zhuǎn)換信息內(nèi)容中的HTML字符
String phone=infoSingle.getInfoPhone(); //獲取聯(lián)系電話
phone = phone.replaceAll(",","●"); //替換“,”符號(hào)
String linkman=infoSingle.getInfoLinkman(); //獲取聯(lián)系人
String email=infoSingle.getInfoEmail(); //獲取E-mail地址
String date=DoString.dateTimeChange(new java.util.Date()); //獲取當(dāng)前時(shí)間并轉(zhuǎn)換為字符串格式
String state="0"; //設(shè)置已審核狀態(tài)為0
String payfor="0"; //設(shè)置已付費(fèi)狀態(tài)為0
Object[] params={type,title,content,linkman,phone,email,date,state,payfor};
String sql="insert into tb_info values(?,?,?,?,?,?,?,?,?)";
int i=myOp.OpUpdate(sql,params); //調(diào)用業(yè)務(wù)對(duì)象的OpUpdate()方法向數(shù)據(jù)表中插入記錄
if(i<=0) //操作失敗
addFieldError("addE",getText("city.info.add.E")); //保存失敗提示信息
else { //操作成功
sql="select * from tb_info where info_date=?"; //生成查詢剛剛發(fā)布信息的SQL語(yǔ)句
Object[] params1={date};
int infoNum=myOp.OpSingleShow(sql, params1).getId(); //獲取剛剛發(fā)布信息的ID值
addFieldError("addS",getText("city.info.add.S")+infoNum); //保存成功提示信息
}
}
return SUCCESS;
}
4.配置cityinfo.xml文件
對(duì)信息發(fā)布請(qǐng)求的配置,與列表顯示某類別中所有信息請(qǐng)求的配置相同,可參看例程34。
1.8.4 單元測(cè)試
在進(jìn)行軟件開(kāi)發(fā)的過(guò)程中,避免不了出現(xiàn)錯(cuò)誤或未發(fā)現(xiàn)的Bug,這些錯(cuò)誤和Bug發(fā)現(xiàn)得越早,對(duì)后面的開(kāi)發(fā)和維護(hù)越有利,因此測(cè)試在軟件開(kāi)發(fā)的過(guò)程中顯得越來(lái)越重要。軟件測(cè)試通常可分為單元測(cè)試、綜合測(cè)試和用戶測(cè)試,其中單元測(cè)試是程序員在開(kāi)發(fā)過(guò)程中最為常用的。
1.單元測(cè)試概述
具體來(lái)說(shuō),單元就是指一個(gè)可獨(dú)立完成某個(gè)操作的程序元素,通常為方法或過(guò)程,因此所謂單元測(cè)試,就是針對(duì)這個(gè)方法或過(guò)程進(jìn)行的測(cè)試。但通常情況下,很少存在不與其他方法發(fā)生調(diào)用與被調(diào)用關(guān)系的方法,所以也可將對(duì)一組用來(lái)完成某個(gè)操作的方法或過(guò)程進(jìn)行的測(cè)試稱為單元測(cè)試。
對(duì)單元的理解可歸納為以下幾點(diǎn):
不可再分的程序模塊。
該模塊實(shí)現(xiàn)了一個(gè)具體的功能。
實(shí)現(xiàn)了某一功能的模塊,與程序中其他模塊不發(fā)生關(guān)系。
對(duì)于面向過(guò)程的語(yǔ)言來(lái)說(shuō),如C語(yǔ)言,進(jìn)行的單元測(cè)試一般針對(duì)函數(shù)或過(guò)程,而像Java這種面向?qū)ο蟮恼Z(yǔ)言,單元測(cè)試通常是針對(duì)類。
對(duì)單元測(cè)試的理解可歸納為以下幾點(diǎn):
它是一種驗(yàn)證行為。
程序中的每一項(xiàng)功能都可以通過(guò)單元測(cè)試來(lái)驗(yàn)證其正確性。這為以后的開(kāi)發(fā)提供支持,就算是開(kāi)發(fā)后期,也可以輕松地增加功能或更改程序結(jié)構(gòu),而不用擔(dān)心這個(gè)過(guò)程中會(huì)破壞重要的東西,而且為代碼的重構(gòu)提供了保障。這樣,開(kāi)發(fā)員可以更自由地對(duì)程序進(jìn)行改進(jìn)。
它是一種設(shè)計(jì)行為。
編寫單元測(cè)試將使開(kāi)發(fā)員從調(diào)用者的角度觀察、思考。特別是先寫測(cè)試,迫使開(kāi)發(fā)人員把程序設(shè)計(jì)成易于調(diào)用和可測(cè)試的。
它是一種編寫文檔的行為。
單元測(cè)試是一種無(wú)價(jià)的文檔,它是展示類或函數(shù)如何使用的最佳文檔。這份文檔是可編譯、可運(yùn)行的,并且永遠(yuǎn)保持與代碼同步。
2.單元測(cè)試帶來(lái)的好處
對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),進(jìn)行單元測(cè)試可以大大減少程序的調(diào)試時(shí)間及程序中的Bug。
對(duì)于整個(gè)項(xiàng)目來(lái)說(shuō),減少了調(diào)試時(shí)間,縮短了項(xiàng)目開(kāi)發(fā)周期。對(duì)項(xiàng)目中的模塊進(jìn)行單元測(cè)試后,保證項(xiàng)目最后交付給用戶進(jìn)行測(cè)試時(shí)有可靠依據(jù)。
對(duì)于測(cè)試人員來(lái)說(shuō),減少了反饋的問(wèn)題。
最主要的是,為項(xiàng)目的后期維護(hù)帶來(lái)了很大的方便,并可減少后期維護(hù)的費(fèi)用。
3.JUnit單元測(cè)試工具的介紹與使用
JUnit是程序單元測(cè)試的框架,專門用于測(cè)試Java開(kāi)發(fā)的程序。同類產(chǎn)品還包括NUnit(.Net)、CPPUnit(C++),都屬于xUnit中的成員。目前JUnit的最新版本是JUnit 4.4。在Eclipse開(kāi)發(fā)工具中已經(jīng)集成了JUnit的多個(gè)版本,本節(jié)將介紹如何在Eclipse中使用JUnit進(jìn)行單元測(cè)試。在介紹JUnit的使用之前,先來(lái)看一下測(cè)試成功與失敗后的運(yùn)行結(jié)果,如圖1.43和圖1.44所示。