本示例代码使用了JQuery、AJAX技术局部刷新分页内容,并将用户浏览过的分页内容缓存在浏览器端,即显示当前页DOM元素,隐藏其他页DOM元素。并在请求换页的JavaScript函数中,根据页id获得请求页DOM元素,若不为空则显示,隐藏原页DOM元素,若为空则发出AJAX请求新页内容。
本示例代码用最少量的交互操作实现了电子商务网站通常的产品分页查询、多元排序业务需求,节省服务器资源,降低服务器负担,使得服务器在同等条件下快速响应更大规模的并发用户操作。
本示例代码并未将DAO层独立出来,而是应用了一个我自己编写的通用DAO工具类,感兴趣者可以到以下地址下载:
Model业务层BookListAction.java代码:
package tarena.dangdang.actions.category;
import hjk.java.dao.SimpleDAO;
import java.util.ArrayList;
import java.util.List;
import tarena.dangdang.actions.BaseActionSupport;
import tarena.dangdang.domain.DCategory;
import tarena.dangdang.domain.DProduct;
import com.opensymphony.xwork2.ActionContext;
public class BookListAction extends BaseActionSupport {
// input
private Integer order;
private Integer pid;
private Integer cid;
private int currentPage = 1;
private int pageSize = 5;
// output
private List<DCategory> cats = new ArrayList<DCategory>();//分类列表
private List<DProduct> pros = new ArrayList<DProduct>();//产品列表
private int ordered = 0;// 用于输出当前排序方式,0为默认排序
private int totalPage;//总页数
private int total;// 产品总数量
private String pname;// 二级分类名
private String cname;// 三级分类名
//local
private String orderCommand;
public String execute() {
//从应用环境获得DAO:
SimpleDAO<DCategory> daoCat = (SimpleDAO<DCategory>) ActionContext
.getContext().getApplication().get("DCategory");
if (daoCat == null) {
daoCat = new SimpleDAO<DCategory>(DCategory.class);
ActionContext.getContext().getApplication().put("DCategory", daoCat);
}
SimpleDAO<DProduct> daoPro = (SimpleDAO<DProduct>) ActionContext
.getContext().getApplication().get("DProduct");
if (daoPro == null) {
daoPro = new SimpleDAO<DProduct>(DProduct.class);
ActionContext.getContext().getApplication().put("DProduct", daoPro);
}
// 处理排序问题
//System.out.println("order:" + order + " cid:" + cid + " pid:" + pid);
boolean orderFlag = false;
if (order != null) {
orderFlag = true;
ordered = order;
switch (order) {
case 0:
orderCommand = "";
break;
case 1:
orderCommand = " order by p.addTime desc";
break;
case 2:
orderCommand = " order by p.saleCount desc";
break;
case 3:
orderCommand = " order by p.dangPrice desc";
break;
case 4:
orderCommand = " order by p.dangPrice";
break;
case 5:
orderCommand = " order by p.commentCount desc";
break;
case 6:
orderCommand = " order by p.score desc";
break;
case 7:
orderCommand = " order by p.publishTime desc";
break;
}
}
// 加载栏目
String hql = "select distinct cat from DCategory cat where cat.parentId="
+ pid;
cats = daoCat.findByHql(hql);
pname = ((DCategory) daoCat.findById(pid)).getName();
// 加载产品信息
Integer id = cid == null ? pid : cid;
hql = "select p from DProduct p join p.cats cat where cat.id=" + id;
if (orderFlag) {
hql = hql + orderCommand;
}
pros = daoPro.findPageByHql(hql, currentPage, pageSize);
// 统计总页数
totalPage = countTotalPage();
//System.out.println(pname + ":" + cname);
if (orderFlag) {
return "order";
} else {
return "success";
}
}
public int getOrdered() {
return ordered;
}
public void setOrdered(int ordered) {
this.ordered = ordered;
}
public Integer getOrder() {
return order;
}
public void setOrder(Integer order) {
this.order = order;
}
/**
* 统计总页数
*
* @return
*/
public int countTotalPage() {
int pages = 0;
int totalRecord = 0;
// 如果点击子栏目,获取子栏目的产品数量
for (DCategory c : cats) {
// 统计所有栏目的总数量
total += c.getProductNum();
// 获取当前浏览栏目的产品数量,计算总页数
if (c.getId().equals(cid)) {
cname = c.getName();
totalRecord = c.getProductNum();
}
if (c.getId().equals(pid)) {
pname = c.getName();
}
}
// 如果点击了"全部",总记录数等于total
if (cid == null) {
totalRecord = total;
}
if (totalRecord == 0) {
pages = 1;
} else if (totalRecord % pageSize == 0) {
pages = totalRecord / pageSize;
} else {
pages = totalRecord / pageSize + 1;
}
return pages;
}
//struts2框架执行数据传输所需要的getter、setter方法:
……
}
控制层struts2配置:
<action name="booklist" class="tarena.dangdang.actions.category.BookListAction">
<param name="pageSize">5</param>
<result name="success">/category/book_list.jsp</result>
<result name="order">/category/order_list.jsp</result>
</action>
视图层book_list.jsp代码:
<%@page contentType="text/html;charset=utf-8"%>
<%@taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>当当图书 – 全球最大的中文网上书店</title>
<link href="../css/book.css" rel="stylesheet" type="text/css" />
<link href="../css/second.css" rel="stylesheet" type="text/css" />
<link href="../css/secBook_Show.css" rel="stylesheet" type="text/css" />
<link href="../css/list.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="../js/jquery-1.4.min.js"></script>
<script type="text/javascript">
function getMouseXY(e){
var posx=0,posy=0;
if(e==null) e=window.event;
if(e.pageX || e.pageY){
posx=e.pageX; posy=e.pageY;
}
else if(e.clientX || e.clientY){
if(document.documentElement.scrollTop){
posx=e.clientX+document.documentElement.scrollLeft;
posy=e.clientY+document.documentElement.scrollTop;
}
else{
posx=e.clientX+document.body.scrollLeft;
posy=e.clientY+document.body.scrollTop;
}
}
return {
X : posx,
Y : posy
}
}
//为产品图片加入鼠标移动事件(动态预览产品大图):
function addImgEvent(){
var x = 20;
var y = 10;
$(".dang_img").hover(
function(){
var mouse = getMouseXY();
var img_src = $(this).attr("src");
$("#tooltip img").attr("src",img_src);
$("#tooltip").css("top",(mouse.Y+y) + "px").css("left",(mouse.X+x) + "px").show();
},
function(){
$("#tooltip").hide();
}
);
}
$(function(){
addImgEvent();
});
</script>
<script type="text/javascript">
//定义全局变量
var order_num=0;
var currentPage = ${currentPage};//此/${}符的意义是:以EL表达式取得action属性值(服务器端处理),非Jquery前缀符.下同。
var cur_order = ${ordered};
var totalPage = ${totalPage};
var cur_page_id = "page_${currentPage}_order_${ordered}";
function order(sel){
cur_order = $(sel).val();
//如果所请求的排序方式等于当前排序方式,则不做处理:
if(cur_order==order_num) {
return;
}else{
order_num=cur_order;
}
//AJAX请求排序数据局部刷新页面:
$("#dyn_list").html("<img src='../images/loading.gif'/>正在加载中...");
$.get("../category/booklist.action?pid=${pid }&cid=${cid }&order="+cur_order, function(data) {
$("#dyn_list").html(data);
currentPage=1;
$("#current_page_num").text(currentPage);
if(currentPage>=totalPage){
$("#next_page_gif").hide();
}
if(currentPage>1){
$("#pre_page_gif").show();
}
});
}
//定位下一页
function next_page(){
currentPage++;
$("#current_page_num").text(currentPage);
if(currentPage>=totalPage){
$("#next_page_gif").hide();
}
if(currentPage>1){
$("#pre_page_gif").show();
}
change_page();
}
//定位上一页
function pre_page(){
currentPage--;
$("#current_page_num").text(currentPage);
if(currentPage<totalPage){
$("#next_page_gif").show();
}
if(currentPage<=1){
$("#pre_page_gif").hide();
}
change_page();
}
//换页通用代码部分:
function change_page(){
var new_page_id = "page_"+currentPage+"_order_"+cur_order;
var cur_page = document.getElementById(cur_page_id);
cur_page_id = new_page_id;
var new_page = document.getElementById(new_page_id);
//如果浏览器DOM元素树中存在页缓存,则隐藏当前页,显示所请求页:
if(new_page!=null){
$(cur_page).hide();
$(new_page).show();
return;
}
//调用Jquery的ajax函数请求新页数据局部刷新页面:
$.get("../category/booklist.action?pid=${pid }&cid=${cid }¤tPage="+currentPage+"&order="+cur_order, function(data) {
$("#dyn_list").html(data);
addImgEvent();
});
}
</script>
</head>
<body>
<!-- 头部开始 -->
<%@include file="../common/head.jsp"%>
<!-- 头部结束 -->
<div style="width: 962px; margin: auto;">
<a href="#"><img src="../images/default/book_banner_081203.jpg"
border="0" /> </a>
</div>
<div class='your_position'>
您现在的位置:
<font style='color: #cc3300'><strong><a href="../category/main.jsp">当当图书</a> >></strong> </font>
<font style='color: #cc3300'><strong><a href="booklist.action?pid=${pid}">${pname}</a> >></strong> </font>
<font style='color: #cc3300'><strong><a href="booklist.action?pid=${pid }&cid=${cid }">${cname}</a></strong> </font>
</div>
<div class="book">
<!--左栏开始-->
<div id="left" class="book_left">
<div id="__fenleiliulan">
<div class=second_l_border2>
<h2>
分类浏览
</h2>
<ul>
<li>
<div>
<s:if test="cid == null">
<div class=second_fenlei3>
全部(${total })
</div>
</s:if>
<s:else>
<div class=second_fenlei>
<a href="booklist.action?pid=${pid}">全部(${total })</a>
</div>
</s:else>
</div>
</li>
<div class=clear></div>
<s:iterator value="cats" var="c1">
<!--三级分类开始-->
<li>
<div>
<s:if test="#c1.id==cid">
<div class=second_fenlei3>
${c1.name } (${c1.productNum })
</div>
</s:if>
<s:else>
<div class=second_fenlei>
<a href="booklist.action?pid=${pid }&cid=${c1.id }">${c1.name } (${c1.productNum })</a>
</div>
</s:else>
</div>
</li>
<div class="clear"></div>
<!--三级分类结束-->
</s:iterator>
<li>
<div></div>
</li>
</ul>
</div>
</div>
</div>
<!--左栏结束-->
<!--中栏开始-->
<div class="book_center">
<!--图书列表开始-->
<div id="divRight" class="list_right">
<div id="book_list" class="list_r_title">
<div class="list_r_title_text">
排序方式
</div>
<select οnchange='javascript:order(this);' name='select_order' size='1'
class='list_r_title_ml' >
<option value="0">
按默认排序
</option>
<option value="0">
--------------
</option>
<option value="1">
按上架时间 降序
</option>
<option value="0">
--------------
</option>
<option value="2">
按销量 降序
</option>
<option value="0">
--------------
</option>
<option value="3">
按价格 降序
</option>
<option value="4">
按价格 升序
</option>
<option value="0">
--------------
</option>
<option value="5">
按热评数量降序
</option>
<option value="6">
按顾客评分降序
</option>
<option value="0">
--------------
</option>
<option value="7">
按出版时间 降序
</option>
</select>
<div id="divTopPageNavi" class="list_r_title_text3">
<!--分页导航开始-->
<s:if test="currentPage>1">
<div id="pre_page_gif" class='list_r_title_text3a'>
<a name=link_page_pre
href="javascript:pre_page();">
<img src='../images/page_up.gif' /> </a>
</div>
</s:if>
<s:else>
<div id="pre_page_gif" style="display:none" class='list_r_title_text3a'>
<a name=link_page_pre
href="javascript:pre_page();">
<img src='../images/page_up.gif' /> </a>
</div>
</s:else>
<div class='list_r_title_text3b'>
第<span id="current_page_num">${currentPage }</span>页/共${totalPage }页
</div>
<s:if test="currentPage< totalPage">
<div id="next_page_gif" class='list_r_title_text3a'>
<a name=link_page_next
href="javascript:next_page();">
<img src='../images/page_down.gif' /> </a>
</div>
</s:if>
<s:else>
<div id="next_page_gif" style="display:none" class='list_r_title_text3a'>
<a name=link_page_next
href="javascript:next_page();">
<img src='../images/page_down.gif' /> </a>
</div>
</s:else>
<!--分页导航结束-->
</div>
</div>
<div id="dyn_list"><div id="page_${currentPage}_order_${ordered}">
<s:iterator value="pros" var="book">
<!--商品条目开始-->
<div class="list_r_line"></div>
<div class="clear"></div>
<div class="list_r_list">
<span class="list_r_list_book"><a name="link_prd_img" href="detail.action?id=${book.id}">
<img title="${book.productName }" class="dang_img" src="../productImages/${book.productPic}" /> </a> </span>
<h2>
<a name="link_prd_name" href='#'>${book.productName }</a>
</h2>
<h3>
顾客评分:${book.score}
</h3>
<h4 class="list_r_list_h4">
作 者:
<a href='#' name='作者'>${book.author }</a>
</h4>
<h4>
出版社:
<a href='#' name='出版社'>${book.publishing }</a>
</h4>
<h4>
出版时间:<s:date name="#book.publishDate" format="yyyy-MM-dd"/>
</h4>
<h5>
${book.description }
</h5>
<div class="clear"></div>
<h6>
<span class="del">¥${book.fixedPrice}</span>
<span class="red">¥${book.dangPrice}</span>
节省:¥${book.fixedPrice-book.dangPrice}
</h6>
<span class="list_r_list_button">
<a href="../cart/addbook.action?id=${book.id}">
<img src='../images/buttom_goumai.gif' /> </a>
</span>
<span id="cartinfo_${book.id}"></span>
</div>
<div class="clear"></div>
<!--商品条目结束-->
</s:iterator>
</div></div>
<div class="clear"></div>
<div id="divBottomPageNavi" class="fanye_bottom">
</div>
</div>
<!--图书列表结束-->
</div>
<!--中栏结束-->
<div class="clear"></div>
</div>
<!--页尾开始 -->
<%@include file="../common/foot.jsp"%>
<!--页尾结束 -->
<%-- 动态预览图之DOM隐藏元素标签块--%>
<div id="tooltip" style="position:absolute;display:none"><img height='400px' width='300px' alt='产品预览图'></img></div>
</body>
</html>