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

下載本文檔

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

文檔簡(jiǎn)介

第10章圖書顯示、購物車及訂單模塊的實(shí)現(xiàn)10.1圖書顯示模塊10.2購物車模塊10.3訂單模塊

10.1圖書顯示模塊

10.1.1所有圖書列表顯示、查詢及排序功能的實(shí)現(xiàn)

1.圖書列表相關(guān)Web頁面的處理

圖書列表頁面booklist.jsp(使用s:include標(biāo)簽)包含代碼①、②、③、④、⑥?5個(gè)頁面,而代碼⑤是分頁處理代碼,代碼①、②分別是頭頁面和尾頁面,這些在第9章已經(jīng)講解。

booklist.jsp頁面的主要代碼如下(省略所有樣式的定義):<body>

<s:includevalue="Head.jsp"></s:include> ①

<s:formaction=""theme="simple">

<table><tr><td>

<s:includevalue="order.jsp"></s:include> ②

</td><td>

<s:includevalue="search.jsp"></s:include> ③

</td></tr></table>

<hr>

<s:iteratorvalue="#request.records"status="st">

<s:includevalue="onebooklist.jsp"></s:include> ④

</s:iterator>

<table><tr><td>

<s:beanname="org.apache.struts2.util.Counter"id="counter">

<s:paramname="first"value="#request.pageview.pageindex.startindex"/>

<s:paramname="last"value="#request.pageview.pageindex.endindex"/>

<s:ahref="bookListAction.action?page=1">首頁</s:a>

<s:iterator>

<s:iftest="#request.pageview.currentpage!=current-1">

<ahref='bookListAction.action?page=<s:property/>'><s:property/></a>

</s:if>

<s:else><fontcolor="black"><b><s:property/></b></font></s:else>

</s:iterator>

<ahref="bookListAction.action?page=${pageview.totalpage}">尾頁</a>|當(dāng)前第${pageview.currentpage}頁

|共${pageview.totalpage}頁

</s:bean></td></tr></table> ⑤

</s:form>

<s:includevalue="Foot.jsp"></s:include> ⑥

</body>

s:include標(biāo)簽起包含頁面的作用,value屬性是所包含頁面的名字。

代碼④在圖書列表中使用s:iterator標(biāo)簽對(duì)每個(gè)圖書列表項(xiàng)進(jìn)行逐一顯示,其value的屬性值為"#request.records",說明在bookListAction中對(duì)應(yīng)的邏輯函數(shù)會(huì)返回名為records的變量,范圍為request,這個(gè)變量就是所有符合查詢結(jié)果的圖書信息集合,具體可以查看下文中Action的定義。

1)排序頁面(order.jsp)

排序頁面如圖10-1所示,使用下拉列表來選擇排序條件。

其中下拉列表名稱為order,“默認(rèn)”的選項(xiàng)值為null,“上架日期”的選項(xiàng)值為date,“價(jià)格從低到高”的選項(xiàng)值為lowprice,“價(jià)格從高到低”的選項(xiàng)值為highprice。因此,排序頁面order.jsp的主要代碼為:圖10-1排序頁面<s:formaction="bookListAction"method="post">

排序方式:

<s:selectname="order"list="#{null:'默認(rèn)','date':'上架日期','lowprice':'價(jià)格從低到高','highprice':'價(jià)格從高到低'}"></s:select>

<inputtype="image"name="imageField"src="images/a/img_32.jpg"/>

</s:form>在客戶端瀏覽器中的輸出如下:

<selectname="order">

<OPTIONvalue=""selected>默認(rèn)</OPTION>

<OPTIONvalue="date">上架日期</OPTION>

<OPTIONvalue="lowprice">價(jià)格從低到高</OPTION>

<OPTIONvalue="highprice">價(jià)格從高到低</OPTION>

</select>

Struts2標(biāo)簽的s:select表單標(biāo)簽除了我們常用的name、label等屬性外,還有表10-1中的一些屬性。

2)查詢頁面(search.jsp)

查詢頁面如圖10-2所示,使用下拉列表來選擇查詢字段,使用單行文本輸入控件來輸入查詢字段的匹配關(guān)鍵字。圖10-2查詢頁面其中下拉列表的名稱為type,“--查看所有圖書--”的選項(xiàng)值為null,“書名”的選項(xiàng)值為bookName,“書籍類型”的選項(xiàng)為bookType,“作者”的選項(xiàng)值為author,“出版社”的選項(xiàng)值為publisher,匹配關(guān)鍵字的文本輸入控件名稱為keyword。因此,查詢頁面search.jsp的主要代碼為:<s:formaction="bookListAction"method="post">

圖書查詢:

<s:selectname="type"list="#{null:'--查看所有圖書--','bookName':'書名','bookType':'書籍類型','author':'作者','publisher':'出版社'}"></s:select>

<s:textfieldname="keyword"size="40"></s:textfield>

<inputtype="image"name="imageField"src="images/a/img_08.jpg"/>

</s:form>以上表單提交觸發(fā)的Action為bookListAction,其中通過判斷type下拉列表的值來設(shè)置圖書搜索字段,并通過keyword輸入框來獲取對(duì)應(yīng)字段的匹配關(guān)鍵字,實(shí)現(xiàn)匹配關(guān)鍵字的模糊查詢。

type下拉列表的list屬性值直接使用OGNL表達(dá)式來創(chuàng)建列表,列表中的每一項(xiàng)都將作為HTML列表框的一個(gè)選項(xiàng)。在客戶端瀏覽器中的輸出如下:<selectname="type">

<OPTIONvalue="">--請(qǐng)選擇--</OPTION>

<OPTIONvalue="bookName">書名</OPTION>

<OPTIONvalue="bookType">書籍類型</OPTION>

<OPTIONvalue="author">作者</OPTION>

<OPTIONvalue="publisher">出版社</OPTION>

</select>

3)圖書列表項(xiàng)頁面(onebooklist.jsp)

圖書列表項(xiàng)頁面如圖10-3所示,顯示圖書名稱、圖片、作者、出版社、出版時(shí)間、圖書描述和圖書價(jià)格等信息,并提供了購買超鏈接。圖10-3圖書列表項(xiàng)頁面

圖書列表項(xiàng)頁面onebooklist.jsp的主要代碼如下(省略部分樣式):

<table><tr><td>

<ahref="singleBookAction.action?id=${id}"target="_blank">

<imgsrc="${bookPic}"/></a>

</td><td>

<table><tralign="center"><td>

<h5><ahref="singleBookAction.action?id=${id}"target="_blank"><fontcolor="#006ff0">${bookName}</font></a></h5>

<hrwidth="700"></td></tr><tr><td><fontcolor="red">人氣指數(shù):${clickCount}</font>

</td></tr><tr><td>

<fontcolor="grey">作者:</font><fontcolor="#006ff0">${author}</font>

<fontcolor="grey">出版社:</font><fontcolor="#006ff0">${publisher}</font>

<fontcolor="grey">出版時(shí)間:${publishDate}</font>

</td></tr><tr><td>

內(nèi)容簡(jiǎn)介:${description}<br><br>

</td></tr><tralign="right"><td>

<fontcolor="grey"><s>¥${marketPrice}</s></font><fontcolor="red">¥${sellPrice}</font>

<fontcolor="grey">節(jié)?。海?{savedPrice}</font>

<s:iftest="visible">①

<ahref="<s:urlaction="cartAction"/>?id=${id}&&visible=${visible}"><imgsrc=/images/a/cart.gif'></a>

</s:if>

<s:else><ahref="#"><imgsrc="/images/a/quehuo.gif"></a></s:else>

</td></tr></table></td></tr></table>代碼①做了個(gè)條件選項(xiàng),當(dāng)圖書的visible屬性為真時(shí),表示此圖書在貨架上可賣,因此顯示如圖10-3所示的購買圖標(biāo),并觸發(fā)cartAction業(yè)務(wù)(將在10.2節(jié)具體實(shí)現(xiàn));當(dāng)圖書的visible屬性為假時(shí),表示此圖書不在貨架上,顯示缺貨的圖樣。本實(shí)例對(duì)缺貨的處理僅保持接口,并未實(shí)現(xiàn)。

以上所有頁面組合成圖書列表booklist.jsp頁面,也就是本項(xiàng)目的主頁,如圖10-4所示,圖中截取了每頁6條記錄的兩條,讀者能清楚地看到本項(xiàng)目的主頁內(nèi)容。圖10-4項(xiàng)目主頁面

2.實(shí)現(xiàn)圖書列表處理的Action

由于圖書實(shí)體BookInfo的屬性較多,其輸入信息就會(huì)比較復(fù)雜,因此我們介紹另一種直接使用領(lǐng)域?qū)ο蟮姆绞?,就是讓action實(shí)現(xiàn)com.opensymphony.xwork2.ModelDriven接口。ModelDriven讓用戶可以直接操作應(yīng)用程序中的領(lǐng)域?qū)ο?,允許你在Web層和業(yè)務(wù)邏輯層使用相同的對(duì)象。

ModelDriven接口中只有一個(gè)方法:

publicTgetModel()

該方法返回一個(gè)用于接收用戶輸入數(shù)據(jù)的模型對(duì)象。在Web頁面中,這個(gè)模型對(duì)象的屬性可以直接通過屬性名來訪問,在action中也不需要為這個(gè)模型對(duì)象提供JavaBean風(fēng)格的get/set方法。

1)建立模型對(duì)象

下面建立的模型對(duì)象在圖書列表、圖書添加、圖書更

新和單本圖書顯示中都要用到,com.bean.book.BookInfoFormBean的代碼如下,除實(shí)體BookInfo的所有屬性外還包括了分頁頁碼、排序、查詢類別和查詢關(guān)鍵字的定義,這些都是在對(duì)應(yīng)action中要獲取的表

單值。packagecom.bean.book;

importjava.util.Date;

publicclassBookInfoFormBean{

//當(dāng)前選擇分頁頁面

privateintpage=1;

//選定排序順序

privateStringorder;

//查詢類別

privateStringtype;

//查詢關(guān)鍵字privateStringkeyword;

privateIntegerid;

privateStringISBN;

privateStringbookName;

privateStringauthor;

privateStringbookType;

privateStringpublisher;

publicStringbookPic;

privateDatepublishDate;;

privateStringdescription;

privateFloatmarketPrice;

privateFloatsellPrice;

privateBooleanvisible=true;

privateDatecreateDate;

privateIntegerclickCount=1;

privateIntegersellCount=0;

privateBooleancommend=false;

……//省略get/set方法

}

2)完成BookAction.java編碼

代碼如下:

packagecom.action.book;

……//省略導(dǎo)入包

@Controller//用于說明BookAction是spring容器管理的bean類

publicclassBookActionextendsActionSupportimplementsModelDriven<BookInfoFormBean>{

@Resource//在BookAction中注入BookInfoService

privateBookInfoServicebookInfoService;

privateBookInfoFormBeanbookInfoFormBean=newBookInfoFormBean();

publicvoidsetBookInfoService(BookInfoServicebookInfoService){

this.bookInfoService=bookInfoService;

}

publicStringbookList(){

try{

ActionContextct=ActionContext.getContext();

HttpServletRequestrequest=(HttpServletRequest)ct

.get(ServletActionContext.HTTP_REQUEST);PageView<BookInfo>pageview=newPageView<BookInfo>(6,

bookInfoFormBean.getPage());

QueryResult<BookInfo>qr=newQueryResult<BookInfo>();

LinkedHashMap<String,String>aa=newLinkedHashMap<String,String>();

if(bookInfoFormBean.getOrder()!=null

&&!"".equals(bookInfoFormBean.getOrder())){

if(bookInfoFormBean.getOrder().equals("date")){

aa.put("createDate","desc");}elseif(bookInfoFormBean.getOrder().equals("lowprice")){

aa.put("sellPrice","asc");

}else{

aa.put("sellPrice","desc");

}

}

Stringtype=bookInfoFormBean.getType();

if(type!=null&&!"".equals(type)){if(bookInfoFormBean.getKeyword()!=null

&&!"".equals(bookInfoFormBean.getKeyword())){

StringBuffersql=newStringBuffer("o."+type+"like?");

List<Object>pram=newArrayList<Object>();

pram.add("%"+bookInfoFormBean.getKeyword()+"%");

qr=bookInfoService.getScrollData(BookInfo.class,pageview

.getFirstindex(),pageview.getMaxresult(),sql

.toString(),pram.toArray(),aa);

}

}else{①

qr=bookInfoService.getScrollData(BookInfo.class,pageview

.getFirstindex(),pageview.getMaxresult(),aa);

}

pageview.setQueryResult(qr);

//設(shè)置pageview和records兩個(gè)request范圍的變量

request.setAttribute("pageview",pageview);

request.setAttribute("records",pageview.getRecords());

returnSUCCESS;

}catch(Exceptione){

e.printStackTrace();

returnERROR;

}

}

//重寫ModelDriven接口方法

publicBookInfoFormBeangetModel(){

returnbookInfoFormBean;

}

}從以上代碼可以看到實(shí)現(xiàn)了ModelDriven<BookInfoFormBean>接口,并重寫了接口中的getModel()方法,實(shí)現(xiàn)了模型對(duì)象與action的結(jié)合。

代碼中最重要的就是bookList()邏輯方法的實(shí)現(xiàn),也就是商品列表顯示方法。bookList()方法的實(shí)現(xiàn)過程可分為三個(gè)階段來理解:●使用bookInfoFormBean.getOrder()獲取order.jsp中對(duì)排序條件的選擇。條件為空,即在列表中選擇“默認(rèn)”,沒有排序語句;條件不為空,如果為date,即在列表中選擇“上架日期”,那么在查詢條件中設(shè)置按createDate屬性降序排列;如果為lowprice,即在列表中選擇“價(jià)格從低到高”,那么設(shè)置按sellPrice屬性升序排列;其它設(shè)置按sellPrice屬性降序排列?!袷褂胋ookInfoFormBean.getOrder()獲取order.jsp中對(duì)排序條件的選擇。條件為空,即在列表中選擇“默認(rèn)”,沒有排序語句;條件不為空,如果為date,即在列表中選擇“上架日期”,那么在查詢條件中設(shè)置按createDate屬性降序排列;如果為lowprice,即在列表中選擇“價(jià)格從低到高”,那么設(shè)置按sellPrice屬性升序排列;其它設(shè)置按sellPrice屬性降序排列。●使用bookInfoFormBean.getType()獲取search.jsp中對(duì)查詢條件的選擇。條件為空,即在列表中選擇“--查看所有圖書--”,則直接運(yùn)行代碼①,調(diào)用沒有where條件語句的getScrollData()方法?!?bookInfoFormBean.getType()不為空時(shí),使用bookInfoFormBean.getKeyword()方法獲取對(duì)應(yīng)查詢字段的關(guān)鍵字。如果關(guān)鍵字不為空,那么使用StringBuffer(“o.”+type+“l(fā)ike?”)來定義where中的查詢條件,實(shí)現(xiàn)模糊查詢,然后調(diào)用getScrollData()方法完成整個(gè)JPQL語句的執(zhí)行。

bookList()方法最后返回pageview和records兩個(gè)變量,讀者可以在booklist.jsp頁面中看到,它們分別用于分頁數(shù)據(jù)和圖書列表項(xiàng)循環(huán)變量。

3.?Action配置及運(yùn)行

完成了Web頁面和Action的定義后,就必須對(duì)二者進(jìn)行關(guān)聯(lián),也就是對(duì)struts.xml進(jìn)行配置。

@Controller注釋把BookAction定義為spring容器管理的bean類,其默認(rèn)bean名稱為bookAction,因此在struts.xml的配置代碼如下:

<actionname="bookListAction"class="bookAction"method="bookList">

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

</action>10.1.2單本圖書信息顯示的實(shí)現(xiàn)

1.?singlebook.jsp頁面

電子商城應(yīng)通過頁面來具體顯示所有商品的相關(guān)信息,讓用戶充分了解商城中物品的信息。由于商品信息一般都比較多,而在商品列表中只能列出用戶最關(guān)心的信息,因此單本圖書信息頁面的制作是十分必要的。

singlebook.jsp頁面利用action中返回的book變量來獲取圖書的所有信息并顯示,具體代碼如下(運(yùn)行顯示界面見圖10-5):

<h5><s:propertyvalue="#request.book.bookName"/></h5><br>

<hrwidth="600"color="red">

<tablewidth="600"><tr><td>

<imgsrc="<s:propertyvalue="#request.book.bookPic"/>"/></td>

<td><table><tr><td>作者:</td><td><s:propertyvalue="#request.book.author"/></td></tr>

<tr><td>出版社:</td><td><s:propertyvalue="#request.book.publisher"/></td>

<tr><td>上架時(shí)間:</td><td><s:propertyvalue="#request.book.createDate"/>

<tr><tdcolspan="2">

<s:iftest="#request.book.visible">在售</s:if><s:else>停售</s:else></td></tr>

</table></td>

<td><table><tr>

<td>ISBN:</td><td><s:propertyvalue="#request.book.ISBN"/></td></tr><tr><td>出版時(shí)間:</td><td><s:propertyvalue="#request.book.publishDate"/>

<tr><td>所屬分類:</td><td><s:propertyvalue="#request.book.bookType"/></td>

<tr><td>是否推薦:</td>

<td><s:iftest="#mend">是</s:if><s:else>否</s:else>

</td></tr>

</table>

</td></tr></table>

<br>

<table><tr><td>定價(jià):¥<s:propertyvalue="#request.book.marketPrice"/></td>

<td>書城價(jià):¥<s:propertyvalue="#request.book.sellPrice"/></td>

<td>節(jié)省:¥<s:propertyvalue="#request.book.savedPrice"/></td></tr>

<tr><td>人氣指數(shù):<s:propertyvalue="#request.book.clickCount"/></td>

<td>銷售量:<s:propertyvalue="#request.book.sellCount"/></td></tr>

<tr><td>

<s:iftest="#request.book.visible">

<ahref="<s:urlaction="cartAction"/>?id=${id}&&visible=${visible}">

<imgsrc="/images/a/cart.gif"></a>

</s:if>

<s:else><ahref="#"><imgsrc="/images/a/quehuo.gif"></a></s:else></td>

<td><ahref="bookListAction.action">

<imgsrc="/images/buy/as-s-continus.gif"border="0"/></a></td></tr>

</table>

<hrwidth="600"color="blue">

<tablewidth="600">

<tr><td><h3>內(nèi)容簡(jiǎn)介:</h3></td></tr>

<tr><td><s:propertyvalue="#request.book.description"/></td></tr>

</table>

2.?Action的實(shí)現(xiàn)

細(xì)心的讀者會(huì)發(fā)現(xiàn)連接到singleBookAction的地址中有id變量的傳入,這個(gè)id就是每本書的關(guān)鍵字id,能唯一確定單本圖書表的記錄,使用這個(gè)變量通過通用業(yè)務(wù)邏輯的find()函數(shù)就能獲取到該id的圖書記錄值。

在9.1.1節(jié)的com.action.bookBookAction.java中添加singleBook()方法,可實(shí)現(xiàn)單本圖書信息獲取的業(yè)務(wù)邏輯,代碼如下:publicStringsingleBook(){

ActionContextct=ActionContext.getContext();

HttpServletRequestrequest=(HttpServletRequest)ct

.get(ServletActionContext.HTTP_REQUEST);

BookInfobookInfo=bookInfoService.find(BookInfo.class,

bookInfoFormBean.getId());

request.setAttribute("book",bookInfo);

returnSUCCESS;

}

3.?Struts.xml配置及運(yùn)行

完成了Web頁面和Action的定義后,同樣必須對(duì)二者進(jìn)行關(guān)聯(lián),配置struts.xml文件,代碼如下:

<actionname="singleBookAction"class="bookAction"method="singleBook">

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

</action>

重啟Tomcat,運(yùn)行http://localhost/bookSite/singleBookAction.action?id=6的結(jié)果如圖10-5所示。圖10-5單本圖書顯示頁面10.2購?物?車?模?塊

10.2.1購物車的配置文件

1.?beans.xml配置

為了讓讀者更加詳細(xì)地了解Spring容器對(duì)bean的管理,在購物車模塊中我們不采用Spring注解進(jìn)行依賴注入,而使用在beans.xml中配置的方式來完成bean的定義和依賴注入。

在beans.xml中添加如下代碼:<beanid="bookInfoServiceBean"class="com.service.bean.impl.BookInfoServiceBean"/>

<beanid="cartAction"class="com.action.shopping.CartAction"scope="prototype">

<propertyname="bookInfoService">

<reflocal="bookInfoServiceBean"/>

</property>

</bean>

<beanid="cartManageAction"class="com.action.shopping.CartManageAction"scope="prototype"/>

2.?struts.xml配置

對(duì)于購物車模塊,一共涉及兩大部分的action配置,包括購物車action和購物車管理action。

(1)購物車配置的代碼如下:

<actionname="cartAction"class="cartAction">

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

</action>(2)購物車管理配置的代碼如下:

<!--清空購物車-->

<actionname="delete"class="cartManageAction"method="delete">

<resulttype="redirect">cartAction.action</result>

</action>

<!--購物車物品單項(xiàng)刪除-->

<actionname="deleteall"class="cartManageAction"method="deleteAll">

<resulttype="redirect">cartAction.action</result></action>

<!--購物車更新-->

<actionname="updateAmount"class="cartManageAction"method="updateAmount">

<resulttype="redirect">cartAction.action</result>

</action>

購物車的更新主要是圖書數(shù)量的更新,在10.2.3節(jié)將完成購物車管理的一系列功能。10.2.2購物車的實(shí)現(xiàn)

Session的好處是開發(fā)簡(jiǎn)單、效率較高,但相對(duì)內(nèi)存占用會(huì)較多,尤其是訪問量比較大的網(wǎng)站;而數(shù)據(jù)庫的效率顯然也是個(gè)問題。很多時(shí)候一些大型電子商務(wù)網(wǎng)站會(huì)從業(yè)務(wù)角度來綜合使用這兩種方式。具體為:

(1)只有在用戶選擇“添加商品到購物車”時(shí)才創(chuàng)建購物車對(duì)象。要知道大多數(shù)的用戶都處于瀏覽狀態(tài),為每個(gè)光臨的用戶都自動(dòng)創(chuàng)建一個(gè)購物車顯然是不明智的。

(2)將購物車臨時(shí)存儲(chǔ)到Session中有個(gè)好處,就是我們可以為沒有登錄的用戶提供購物車服務(wù),只有在用戶進(jìn)行結(jié)算的時(shí)候才需要登錄。當(dāng)然,我們也可以使用SessionID作為唯一識(shí)別符將購物車存儲(chǔ)到數(shù)據(jù)庫中。

(3)對(duì)于已經(jīng)登錄的用戶,如果他的購物車不為空,我們會(huì)在Session過期時(shí)將他的購物車數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫中,這樣用戶下次進(jìn)入網(wǎng)站的時(shí)候就可以持有上次挑選的商品進(jìn)行一次結(jié)算,這種人性化的方式更加吸引用戶。不過這里面有個(gè)陷阱就是折扣的問題,因?yàn)楹芏啻黉N活動(dòng)中,商品的價(jià)格和日期有關(guān),因此這種方式可能帶來商品價(jià)格上的混亂。

對(duì)于中小型購物網(wǎng)站顯然不用考慮得這么周全。本項(xiàng)目使用Session來實(shí)現(xiàn)購物車。

1.實(shí)現(xiàn)Session監(jiān)聽

利用Session實(shí)現(xiàn)購物車存在的一個(gè)關(guān)鍵解決問題就是Session的監(jiān)聽。

大部分讀者應(yīng)該清楚,Session變量的作用范圍僅限于同一個(gè)IE瀏覽器頁面,如果打開另一個(gè)IE瀏覽器頁面,則Session變量將會(huì)重新賦值。而用戶可能會(huì)打開多個(gè)窗口來查看圖書信息并進(jìn)行購買,要保證用戶的商品都在同一個(gè)購物車中,就要實(shí)現(xiàn)Session創(chuàng)建和摧毀的監(jiān)聽。

1)?Session監(jiān)聽器類

Session監(jiān)聽器類為com.action.shopping.SiteSessionListener.java,具體代碼如下:

packagecom.action.shopping;

importjava.util.HashMap;

importjava.util.Map;

importjavax.servlet.http.HttpSession;

importjavax.servlet.http.HttpSessionEvent;

importjavax.servlet.http.HttpSessionListener;

publicclassSiteSessionListenerimplements

HttpSessionListener{

privatestaticMap<String,HttpSession>sessions=newHashMap<String,HttpSession>();

publicvoidsessionCreated(HttpSessionEventsessionEvent)

{

sessions.put(sessionEvent.getSession().getId(),sessionEvent.getSession());}

publicvoidsessionDestroyed(HttpSessionEventsessionEvent)

{

sessions.remove(sessionEvent.getSession().getId());}

publicstaticHttpSessiongetSession(StringsessionID)

{

returnsessions.get(sessionID);}

publicstaticvoidremoveSession(StringsessionID)

{

if(sessions.containsKey(sessionID))

sessions.remove(sessionID);}

}

2)?Session監(jiān)聽器配置

Session監(jiān)聽器配置在web.xml中,也就是在工程啟動(dòng)時(shí),具體代碼如下:

<listener>

<listener-class>com.action.shopping.SiteSessionListener</listener-

class>

</listener>

3)測(cè)試監(jiān)聽器

(1)不使用監(jiān)聽器。根據(jù)10.2.1節(jié)的配置,新建購物車的action業(yè)務(wù)邏輯,代碼在com.action.shopping.CartAction.java中。

packagecom.action.shopping;

……//省略導(dǎo)入包

publicclassCartActionextendsActionSupport{

privateBookInfoServicebookInfoService;publicvoidsetBookInfoService(BookInfoServicebookInfoService){

this.bookInfoService=bookInfoService;}

publicStringexecute()throwsException

{

ActionContextct=ActionContext.getContext();

HttpServletRequestrequest=(HttpServletRequest)ct.get(ServletActionContext.HTTP_REQUEST);

if(request.getSession().getAttribute("out")==null){

request.getSession().setAttribute("out",newDate());

}

returnSUCCESS;

}

}

新建cart.jsp文件,輸出out變量,即${out},測(cè)試運(yùn)行http://localhost/bookSite/cartAction.action,打開兩個(gè)瀏覽器,發(fā)現(xiàn)顯示的時(shí)間不相同,說明在不同的頁面同一個(gè)Session值不會(huì)被保存。

(2)使用監(jiān)聽器。修改以上的execute方法,代碼如下:

publicStringexecute()throwsException

{

ActionContextct=ActionContext.getContext();

HttpServletRequestrequest=(HttpServletRequest)ct.get(ServletActionContext.HTTP_REQUEST);

Stringsid=request.getParameter("sid");

HttpSessionsession=SiteSessionListener.getSession(sid);

System.out.println(session);

if(session==null){

request.getSession().setAttribute("buycart",newDate());

}

else{

request.setAttribute("message",session.getAttribute("buycart"));

}

returnSUCCESS;

}修改cart.jsp文件,輸出message變量,即${message},測(cè)試運(yùn)行http://localhost/bookSite/cartAction.action,在【console】控制臺(tái)輸出字符串A(A代表訪問的session的sid值,一般如“D6DEC55CEBC4EFB51B8FC52EEAA67181”字樣),另外打開一個(gè)IE窗口,在【console】控制臺(tái)輸出字符串B,而且頁面顯示的時(shí)間不一致。但是當(dāng)把第二個(gè)頁面的訪問地址改成http://localhost/bookSite/cartAction.action?sid=字符串A,則第二個(gè)頁面的時(shí)間就會(huì)與第一個(gè)頁面的時(shí)間一致,這說明Session監(jiān)聽器設(shè)置成功。

在購物模塊中可以把第一個(gè)頁面的時(shí)間看成是購物車的物品,當(dāng)打開新的瀏覽器時(shí)就可以通過Session監(jiān)聽器獲得此購物車的物品。下面進(jìn)入購物車模塊制作的講解。

2.初步實(shí)現(xiàn)購物車功能

實(shí)現(xiàn)購物車功能時(shí),首先要實(shí)現(xiàn)每項(xiàng)購買產(chǎn)品的添加。那么,添加到購物車的購物項(xiàng)應(yīng)該存放哪些相關(guān)數(shù)據(jù)呢?這就是我們這節(jié)首先要解決的問題。

1)購物項(xiàng)輔助類的實(shí)現(xiàn)

編寫購物項(xiàng)類com.bean.BuyItem.java,其中屬性book代表每個(gè)購物項(xiàng)中的書目,屬性amount代表對(duì)應(yīng)購物項(xiàng)中書的數(shù)量,具體代碼如下:

packagecom.bean;

importcom.bean.book.BookInfo;

publicclassBuyItem

{

privateBookInfobook;

privateintamount;

publicBuyItem(){}

publicBuyItem(BookInfobook){

this.book=book;}

publicBuyItem(BookInfobook,intamount){

this.book=book;

this.amount=amount;}

……//省略get/set方法

ublicinthashCode(){

finalintprime=31;

intresult=1;

result=prime*result+((book==null)?0:

book.hashCode());

returnresult;}

publicbooleanequals(Objectobj){

f(this==obj)returntrue;

if(obj==null)returnfalse;

if(getClass()!=obj.getClass())returnfalse;

BuyItemother=(BuyItem)obj;

if(book==null){

if(other.book!=null)returnfalse;

}elseif(!book.equals(other.book))returnfalse;

returntrue;}

}以上hashCode()和equals()兩個(gè)方法的定義表示BuyItem類之間的比較依賴book屬性,也就是book屬性相同的兩個(gè)BuyItem實(shí)例相等,也就是同一本書被看成同一個(gè)購物項(xiàng),如果被多次點(diǎn)擊購買,那么只是在同一個(gè)購物項(xiàng)中增加amount的數(shù)量。

我們可以對(duì)購物項(xiàng)的比較做一個(gè)測(cè)試,建立測(cè)試類junit.test.BuyCartTest.java,測(cè)試購買同一種圖書是否能通過購物項(xiàng)判斷出來,具體代碼如下:packagejunit.test;

……//省略導(dǎo)入包

publicclassBuyCartTest

{@Test

publicvoidtest()

{

BookInfobook1=newBookInfo(1);

BuyItembuyItem1=newBuyItem(book1,5);

BookInfobook2=newBookInfo(1);

BuyItembuyItem2=newBuyItem(book2,9);

System.out.println(buyItem1.equals(buyItem2));

}

}

2)購物車類的實(shí)現(xiàn)

有了購物項(xiàng)的定義,那么只有建立購物車類,再把購物項(xiàng)添加到購物車就可以完成購物車的業(yè)務(wù)邏輯。

建立購物車com.bean.BuyCart.java,其中包含購物項(xiàng)列表items和添加購物項(xiàng)功能addItem()方法,具體代碼如下:packagecom.bean;

……//省略導(dǎo)入包

publicclassBuyCart

{privateList<BuyItem>items=newArrayList<BuyItem>();

……//省略get/set方法

publicvoidaddItem(BuyItemitem)

{if(!items.contains(item))

items.add(item);

else

{for(BuyItembi:items)

{if(bi.equals(item))

{bi.setAmount(bi.getAmount()+1);

break;

}}}}

在addItem()方法中先判斷購物項(xiàng)列表中是否存在要購買的書,如果不存在,則添加購物項(xiàng);如果存在該購物項(xiàng),則累加其購買數(shù)量。

3)購物車Action的實(shí)現(xiàn)

實(shí)現(xiàn)了購物車類,就完成了購物車Action的邏輯處理輔助類的編寫。因此,根據(jù)前面的session測(cè)試方法,修改com.action.shopping.CartAction.java文件,即可實(shí)現(xiàn)Web頁面的輸出和購物車物品的獲取。具體代碼如下:packagecom.action.shopping;

……//省略導(dǎo)入包

publicclassCartActionextendsActionSupport{

privateIntegerid;

privateBooleanvisible;

privateBookInfoServicebookInfoService;

……//省略get/set方法

publicStringexecute()throwsException{ActionContextct=ActionContext.getContext();

HttpServletRequestrequest=(HttpServletRequest)ct.get(ServletActionContext.HTTP_REQUEST);

HttpServletResponseresponse=(HttpServletResponse)ct.get(ServletActionContext.HTTP_RESPONSE);

BuyCartbuyCart=(BuyCart)request.getSession().getAttribute("buycart");

//判斷其它頁面有無buyCart存在

if(buyCart==null){Stringsid=WebUtil.getCookieByName(request,"buyCartID");

if(sid!=null)

{HttpSessionsession=SiteSessionListener.getSession(sid);

if(session!=null)

buyCart=(BuyCart)session.getAttribute("buycart");

if(buyCart!=null)

{SiteSessionListener.removeSession(sid);

request.getSession().setAttribute("buycart",buyCart);

WebUtil.addCookie(response,"buyCartID",request.getSession().getId(),request.getSession().getMaxInactiveInterval());

}

}

}

//若其它頁面無buyCart存在,則新建session

if(buyCart==null)

{buyCart=newBuyCart();

request.getSession().setAttribute("buycart",buyCart);//session的最大存放時(shí)間為30分鐘

WebUtil.addCookie(response,"buyCartID",request.getSession().getId(),request.getSession().getMaxInactiveInterval());

}

if(getId()!=null&&getId()>0)

{BookInfobook=bookInfoService.find(BookInfo.class,getId());

if(book!=null&&getVisible()){buyCart.addItem(newBuyItem(book,1));

//把商品放入購物車

}else{System.out.println("停售");}

}

request.getSession().setAttribute("buyCart",buyCart);

returnSUCCESS;

}

}以上代碼中使用了工具類com.utils.WebUtil.java中的addCookie()方法,對(duì)cookies進(jìn)行處理,該類的代碼為:

packagecom.utils;

……//省略導(dǎo)入包

publicclassWebUtil{

publicstaticStringgetCookieByName(HttpServletRequestrequest,Stringname){

Map<String,Cookie>cookieMap=

WebUtil.readCookieMap(request);

if(cookieMap.containsKey(name)){

Cookiecookie=(Cookie)cookieMap.get(name);

returncookie.getValue();

}else{returnnull;}}

protectedstaticMap<String,Cookie>readCookieMap(HttpServletRequestrequest){

Map<String,Cookie>cookieMap=newHashMap<String,Cookie>();

Cookie[]cookies=request.getCookies();

if(null!=cookies){

for(inti=0;i<cookies.length;i++){

cookieMap.put(cookies[i].getName(),cookies[i]);

}}

returncookieMap;

}}

4)測(cè)試簡(jiǎn)單的購物車數(shù)據(jù)

下面我們把cart.jsp頁面改為如下代碼,顯示購買的書名和數(shù)量:

<s:iteratorvalue="#session.buyCart.items"status="st">

${bookInfo.bookName},${amount}<br/>

</s:iterator>重啟服務(wù)器,http://localhost/bookSite/bookListAction.action點(diǎn)擊購買超鏈接,出現(xiàn)購買圖書的名字和數(shù)量列表,打開兩個(gè)窗體,購買的圖書會(huì)自動(dòng)累加說明購物車初步功能完成,如圖10-6所示。圖10-6簡(jiǎn)單購物車頁面

3.完善購物車

現(xiàn)在我們?cè)撟龅氖戮褪峭晟瀑徫镘嚨娘@示頁面,讓頁面中顯示一般購物車通常具備的功能,如提供更新數(shù)量的表單、提供刪除商品的鏈接和提供生成訂單的鏈接等。

1)美化cart.jsp文件

讀者可以自己制作或使用課件中的cart2.jsp(根據(jù)struts.xml配置把文件名改為cart.jsp)來實(shí)現(xiàn)靜態(tài)購物車頁面的美化,參考圖樣見圖10-7。圖10-7靜態(tài)購物車頁面●各項(xiàng)超鏈接:包括單本圖書詳細(xì)信息查看、繼續(xù)挑選商品和進(jìn)入結(jié)算中心。

●圖書購物項(xiàng)列表:包括每項(xiàng)的書名、圖書定價(jià)、商城價(jià)、每本節(jié)省價(jià)和數(shù)量。

●購物車統(tǒng)計(jì)項(xiàng):包括購物車商品總價(jià)和總共節(jié)省費(fèi)用。

●購物車管理操作:包括更新購物項(xiàng)數(shù)量、刪除購物項(xiàng)和刪除購物車,這部分內(nèi)容將在10.2.3節(jié)中講解。

2)各項(xiàng)超鏈接

(1)單本圖書詳細(xì)信息。在每本書的書名上含有單本圖書的詳細(xì)信息鏈接,地址為

<ahref="singleBookAction.action?id=${book.id}"

target="_blank">…</a>,大部分購物車都具有這個(gè)功能,讓買家在確定購買前能再次查看物品的詳細(xì)信息。

(2)繼續(xù)挑選商品。“繼續(xù)挑選商品”圖標(biāo)鏈接的地址為<ahref="bookListAction.action">

……</a>,也就是重新進(jìn)入圖書列表頁面挑選圖書。

(3)進(jìn)入結(jié)算中心。圖中兩個(gè)“進(jìn)入結(jié)算中心”圖標(biāo)鏈接的地址設(shè)置為<ahref="orderAction.action">……</a>,就是進(jìn)入訂單功能模塊,這部分內(nèi)容將在10.3節(jié)中講解。

3)圖書購物項(xiàng)列表

中間的圖書購物項(xiàng)列表使用循環(huán)來實(shí)現(xiàn)各購物項(xiàng)的顯示,代碼參考如下(省略各樣式):

<formname="buycart"action="<s:urlaction="updateAmount"/>"method="post">

<inputtype="hidden"name="method"value=""/>

<table><tr><td><strong>我的購物車?yán)锏纳唐?-馬上購買</strong></td>

<td><divalign=center><strong>市場(chǎng)價(jià)</strong></div></td><tdwidth=181><divalign=center><strong>圖書價(jià)格</strong></div></td>

<tdwidth=73><divalign=center><strong>數(shù)量</strong></div></td>

<tdwidth=66> </td></tr>

<s:iteratorvalue="#session.buyCart.items"status="">

<tr><td><strong><ahref="singleBookAction.action?id=${book.id}"target="_blank">${book.bookName}</a></strong><br/></td><td><s><b>¥${book.marketPrice}元</b></s></td>

<td><palign="center"><b>¥${book.sellPrice}

元</b><br/>

為您節(jié)?。海?{book.savedPrice}元<br/></p></td>

<td><inputtype="text"value="${amount}"name="amount_${book.id}"onkeypress="javascript:InputIntNumberCheck()"maxlength="3"/></td><td><ahref="delete.action?buyitemid=${book.id}">

<imgsrc="/images/buy/delete.gif"/></a></td></tr>

</s:iterator>

</table>

</form>以上通過<s:iteratorvalue=“#session.buyCart.items”>…</s:iterator>循環(huán),對(duì)購物車列表項(xiàng)的數(shù)據(jù)庫信息遍歷,并把圖10-7中的靜態(tài)文字內(nèi)容編寫成動(dòng)態(tài)數(shù)據(jù),分別對(duì)應(yīng)的代碼為:

●圖書名稱:${};

●圖書定價(jià):${book.marketp

溫馨提示

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

評(píng)論

0/150

提交評(píng)論