




版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 汽車玻璃運(yùn)輸安全協(xié)議
- 2025年度調(diào)味品新產(chǎn)品研發(fā)與市場(chǎng)試點(diǎn)合同
- 2025年度體育場(chǎng)館清潔工專業(yè)服務(wù)協(xié)議
- 溝通中的洞察力從觀察他人到改進(jìn)自身演講的途徑
- 2025年度夫妻共同財(cái)產(chǎn)管理及家庭責(zé)任分擔(dān)協(xié)議書
- 2025年度公司管理人員任期制與解聘合同
- 產(chǎn)業(yè)園裝修承包協(xié)議范本
- 2025年度個(gè)人土地承包與農(nóng)業(yè)科技創(chuàng)新合作合同
- 集裝箱吊運(yùn)機(jī)建設(shè)項(xiàng)目可行性研究報(bào)告申請(qǐng)立項(xiàng)備案
- 2025養(yǎng)生館線上線下融合合作合同協(xié)議
- QSB質(zhì)量體系基礎(chǔ)課件
- 小兒高熱驚厥精品課件
- 優(yōu)秀員工榮譽(yù)證書模板
- 三維電生理導(dǎo)航系統(tǒng)技術(shù)參數(shù)
- 三年級(jí)下冊(cè)科學(xué)活動(dòng)手冊(cè)
- 《交通工程CAD》課程教學(xué)大綱(本科)
- 人教版數(shù)學(xué)五年級(jí)下冊(cè) 全冊(cè)各單元教材解析
- 換班申請(qǐng)表(標(biāo)準(zhǔn)模版)
- 者陰村戰(zhàn)友紀(jì)念者陰山對(duì)越自衛(wèi)還擊作戰(zhàn)30周年聯(lián)誼會(huì)計(jì)劃2
- 基于單片機(jī)的電子廣告牌設(shè)計(jì)畢業(yè)設(shè)計(jì)論文
- 承插型盤扣式支模架專項(xiàng)施工方案
評(píng)論
0/150
提交評(píng)論