分页功能应该说在每个项目中是必不可少的,好多公司也都有自己的一套实现方案(像我们公司有自己的组件库,只要继承一个form类就可以了,然后在页面里加一个分页的标签就能实现分页功能),我之前刚开始学WEB的时候写过一个很简陋的分页功能。
这段时间有空了,就拿出以前做过的一个练习项目——电子商务(网上购书系统)网站重写一下分页功能,增强分页功能的可重用性及可维护性,不多说费话了我们开始吧……
项目工作环境:
- JDK1.5
- MyEclipse5.5
- Tomcat 5.5.23
- Mysql 5
使用技术:
jsp、struts、EL表达式
类及页面:
- 一个控制分页属性的POJO是必不可少的——Page.java
- 一个实现分页功能的Action——ControlPageAction.java
- 一个分页页面——swappage.jsp
实现原理:
我向来是以代码来讲原理,我们先看看源码吧:
首先定义一个POJO类——Page.java
package net.yanhl.page;


public class Page ...{
int ipage=5; //分页单位
int allpage; //总页数
int pages; //接受的页码变量
int cpage=1; //当前页
int spage; //开始页

public int getAllpage() ...{
return allpage;
}


public void setAllpage(int allpage) ...{
this.allpage = allpage;
}


public int getCpage() ...{
return cpage;
}


public void setCpage(int cpage) ...{
this.cpage = cpage;
}


public int getIpage() ...{
return ipage;
}


public void setIpage(int ipage) ...{
this.ipage = ipage;
}


public int getPages() ...{
return pages;
}


public void setPages(int pages) ...{
this.pages = pages;
}


public int getSpage() ...{
return spage;
}


public void setSpage(int spage) ...{
this.spage = spage;
}
}

里面的属性都有注释就不多讲了。
控制类—— ControlPageAction.java
package net.yanhl.action;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.yanhl.dao.IProductDAO;
import net.yanhl.factory.DAOFactory;
import net.yanhl.page.Page;
import net.yanhl.pojo.Product;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;


public class ControlPageAction extends Action ...{


/** *//**
* 分页原理:
*
*/
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)

throws Exception ...{
HttpSession session = request.getSession();
String target = request.getParameter("target");// 要分页查找的对象及查找后转向的对象
Page page = (Page) session.getAttribute("curPage");
IProductDAO dao = (IProductDAO) DAOFactory.getDAO("ProductDAO");


/**//*
* 这里把总的记录数放到session里是为了减少对数据库的访问次数 如果page.setAllpage(dao.getMacColum() /
* page.getIpage() + 1);这样写的话访问数据库的次数是:用户访问次数*2
* 而如果page.setAllpage(maxColum / page.getIpage() +
* 1);则是用户访问次数+1,因为第一次要去查找总记录数
*/
int maxColum = -1;// 一共多少条记录

if (session.getAttribute("maxColum") == null) ...{
maxColum = dao.getMaxColum();
session.setAttribute("maxColum", maxColum);

} else ...{
maxColum = Integer.valueOf(session.getAttribute("maxColum").toString());
}

// ===================== 逻辑判断开始============================
// 第一次访问给此用户设置一个page

if (page == null) ...{
page = new Page();
page.setAllpage(maxColum / page.getIpage() + 1);
}

// 用户要访问的页码

if (request.getParameter("pages") == null) ...{
page.setPages(1);

} else ...{
page.setPages(Integer.parseInt(request.getParameter("pages")));
}

// 对应于用户输入的页数<input tyep=text name='pages'>

if (request.getParameter("inputPages") != null) ...{
page.setPages(Integer.parseInt(request.getParameter("inputPages")));
}

//如果用户输入的页码大于总页码或小于0则直接返回

if (page.getPages() > page.getAllpage() || page.getPages() <= 0) ...{
return mapping.findForward(target);
}

// current page

if (page.getPages() > page.getAllpage()) ...{
page.setCpage(1);

} else ...{
page.setCpage(page.getPages());
}

// start page
page.setSpage(((page.getPages() - 1) * page.getIpage()));

// ================================= 逻辑判断结束===============================



if ("product".equals(target)) ...{
Map<Integer, Product> products = dao.findAll(page.getSpage() + 1, page.getSpage() + page.getIpage());
request.setAttribute("result", products);
mapping.findForward("product");
}
session.setAttribute("curPage", page);
session.setAttribute("countRows", maxColum);

return mapping.findForward(target);
}
}

需要使用分页功能的页面——productList.jsp:

<%...@ page
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
%>

<%...@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<%...@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
<html>
<head>
<LINK href="css/tarena.css" rel=stylesheet>
</head>
<!--文件体开始-->

<%...
if(request.getAttribute("result") == null){
%>
<jsp:forward page="/controlPage.do?target=product"></jsp:forward>
<%}%>
<body>
<!--这里的target隐藏属性就定义了ControlPageAction要转向的页面 -->
<input type=hidden name="target" value="product">
<table cellpadding=3 cellspacing=1 align=center class=tableborder1>
<tr>
<td valign=middle align=center height=25 background="images/bg2.gif" width=""><font color="#ffffff"><b>序号</b></font></td>
<td valign=middle align=center height=25 background="images/bg2.gif" width=""><font color="#ffffff"><b>产品编号</b></font></td>
<td valign=middle align=center height=25 background="images/bg2.gif" width=""><font color="#ffffff"><b>产品名称</b></font></td>
<td valign=middle align=center height=25 background="images/bg2.gif" width=""><font color="#ffffff"><b>价格</b></font></td>
<td valign=middle align=center height=25 background="images/bg2.gif" width=""><font color="#ffffff"><b>操作</b></font></td>
</tr>
<c:forEach var="product" items="${requestScope.result}" varStatus="i">
<tr>
<td class=tablebody2 valign=middle align=center width="">${i.index +1 }</td>
<td class=tablebody1 valign=middle width="" align="center">${product.value.productid}</td>
<td class=tablebody1 valign=middle width=""> <a href="javascript:view(${product.value.productid });">${product.value.name }</a></td>
<td class=tablebody2 valign=middle align=center width="">${product.value.baseprice }</td>
<td class=tablebody1 valign=middle align=center width=""><a href="${pageContext.request.contextPath }/shop/addProduct.do?productid=${product.value.productid }">
<img border="0" src="images/car_new.gif" width="97" height="18"></a> </td>
</tr>
</c:forEach>
<tr>
<jsp:include flush="true" page="swappage.jsp?target=product"></jsp:include>
</tr>
</table>
</body>
</html>
<!-- javascript start -->

<script type="text/javascript">...

/**//**
查看
**/

function view(id)...{
window.open("productDetail.do?productid=" + id);
}
</script>
<!-- javascript end -->

struts-config.xml:
<forward name="product" path="/productList.jsp"></forward>

<!-- 分页查询实现Action -->
<action path="/controlPage"
type="net.yanhl.action.ControlPageAction">
</action>
DAO实现类——ProductDAO中的查找方法:

public Collection findAll(final int start,final int end)...{

HibernateCallback callback = new HibernateCallback() ...{


public Object execute(Session session) ...{
return session.createQuery("from Product p order by p.name")
.setFirstResult(start-1)
.setMaxResults(end)
.list();
}

};

return delegate.findAll(callback);
}
到现在所有文件都已经准备好了,实现原理其实很简单:
把swappage.jsp文件加到要使用分页功能的页面中(<jsp:include>),然后swappage.jsp中的所有链接都是去执行ControlPageAction类,在点击swappage.jsp中的链接的时候会给ControlPageAction传递一系列参数:target、pages等,这个target指的是struts-config.xml文件中指定的名字,比如这里的product对应于productList.jsp,当然这个是在struts-config.xml中配置好的,当ControlPageAction执行通过DAO获得数据后判断target是哪一个,然后把对应的对象集合放到requestScope中,再把当前的page对象放到sessionScope中,最后再跳转到target所指定的页面,转到target这样就完成了分页功能。
具体的实现细节在文件及类中都有注释,相信大家很快能实现分页功能,祝你成功……