正文

都市供求信息網(wǎng)(19)

JSP項(xiàng)目開(kāi)發(fā)案例全程實(shí)錄(第2版) 作者:明日科技


代碼貼士

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所示。


上一章目錄下一章

Copyright ? 讀書(shū)網(wǎng) m.ranfinancial.com 2005-2020, All Rights Reserved.
鄂ICP備15019699號(hào) 鄂公網(wǎng)安備 42010302001612號(hào)