传统分页功能的实现
之前一直认为分页是很繁琐的事情,随着时间的积累,这一次再次接触到分页功能,思路清晰了许多,其实分页无非就是根据页面的显示信息获取分页的几个值,大体上这些值也可以分类的:
比如:页面传递的值或者默认的值;通过查询数据库的内容来获取的值;通过推导公式计算出来的值。
(其实推导都是很简单的,只不过一提公式脑袋就大了,这是典型的不动脑的习惯,我本人属于此类,呵呵,所以大家还是多动脑,动脑,脑袋越动越灵活。)
下面我们分析关于分页所需要哪些内容:其实基本上所有网页的分页都是大同小异的,或许我们有时候会有很多分页工具封装好了这些分页内容,比如mybatis的pageHelper类,直接封装好了分页信息,我们直接拿来用即可。
但是明白了分页的最基本的原理,这些分页工具会起到画龙点睛的作用。下面我们开看看具体的分页信息:
1、创建一个pageBean类:封装分页所需要的几个字段,这个类是为了代码复用,因为分页这个功能很多模块可能都会涉及到,到时候我们直接调用即可。
首先我们看一个页面:

这是一个分页的典型的图片,基本很多分页都是基于此来开发的,下面看下有多少分页字段:
首先分页是对什么进行分页:页面要显示数据列表,而这些数据列表需要分页显示。所以我们要获取这些数据列表,然后加上分页的信息,将数据列表实现分段。
即字段:
recordList 每个页面显示的记录的列表。(这里涉及到每页都是从多少条记录开始显示的)
总记录数是多少:recordCount
我们看到页次:当前页/总共的页数 即 currentPage / pageCount
每页显示的条数:pageSize
另外我们看到我们想看哪一页就点击哪一页,总共要显示多少个页码,是都显示还是只显示一部分页码(这里又有一种方案),想跳转到哪一页就跳转到哪一页。
根据上面的分析所得:分页的信息就是这些,接下来就是如何获取这些信息对应的数据的值,然后将此pageBean封装好这些信息然后反馈到页面,页面获取到这些信息进行显示。
这里我们分三类:
(1)页面传递的或者默认可以设置的字段:每页显示条数:pageSize (可以默认自己设置多少值) ;当前页currentPage (通常默认为第一页)
(2)需要查询数据库获取的字段的值:
显示列表的总记录数recordCount:SELECT COUNT(*) FROM table WHERE 条件
加上分页后获取当前页面显示的记录的条数recordList:即每页页面显示的数据列表:
getSession().createQuery(//
"FROM Reply r WHERE r.topic= ? ORDER BY r.postTime ")
.setParameter(0,topic)
.setFirstResult((pageNum-1)*10)
注意这里有隐含的信息:比如我们设置每页显示10条记录,总共33条记录,第一页显示0--10记录数,第二页显示10--20,第三页显示30---40;即么每页显示10条。
所以这里设置每页的开始记录就是:(pageNum-1)*10
.setMaxResults(pageSize)
.list();
(3)获取到上面这些字段后,我们分析下如何通过公式计算剩下的字段:
总共多少页:pageCount,
页码开始的索引页beginPageIndex,页面结束的索引:endPageIndex(为什么要设置这两个字段呢,因为我们要进行列表的显示)

//计算剩余的三个值,根据公式进行计算
pageCount=(recordCount+pageSize-1)/pageSize;
/*计算开始页索引和结束页索引:这里我们定义总共显示10个页码。分几种情况
* 第一:当总共页数pageCount不足10页的时候,则显示全部页码
* 第二:当总共页数超过10页时,则显示当前页的前4页和当前页的后5页。
* 但是这里又有两种情况:如果总共有11页,当前页是3,则3-4=-1,这是不可以的,
* 即当前面的页面少于4个时,这个时候显示前十页。
* 同理:当后面的页面不足5个时,显示后10页。
*/
if (pageCount<=10) {
beginPageIndex=1;
endPageIndex=pageCount;
}else{
beginPageIndex=currentPage-4;
endPageIndex=currentPage+5;
if (beginPageIndex-4<1) {
beginPageIndex=1;
endPageIndex=10;
}
if (endPageIndex>pageCount) {
beginPageIndex=currentPage-10+1;
endPageIndex=pageCount;
}
}
}
最后一步就是将封装好内容的pageBean传递到页面:页面获取响应的值
2、修改jsp页面信息
这里主要是注意struts2标签内部使用OGNL表达式,在HTML标签里面或者标签体使用EL表达式。
OGNL用%{} EL表达式用${}获取。
3、具体代码如下:
package cn.itcast.oa.domain;
import java.util.List;
public class PageBean {
//主要是对分页的几个字段属性进行封装,这些字段都可以根据jsp页面来进行推断出来
//这些可以页码获取
private int currentPage;//当前页码
private int pageSize;//每页显示多少条记录
//这些可以数据库获取
private List recordList;//本页的数据列表
private int recordCount;//总记录数
//这些可以根据上面的计算得到
private int pageCount;//总共多少页
private int beginPageIndex;//页码的开始索引
private int endPageIndex;//页码的结束索引
public PageBean(int currentPage, int pageSize, List recordList, int recordCount) {
super();
this.currentPage = currentPage;
this.pageSize = pageSize;
this.recordList = recordList;
this.recordCount = recordCount;
//计算剩余的三个值,根据公式进行计算
pageCount=(recordCount+pageSize-1)/pageSize;
/*计算开始页索引和结束页索引:这里我们定义总共显示10个页码。分几种情况
* 第一:当总共页数pageCount不足10页的时候,则显示全部页码
* 第二:当总共页数超过10页时,则显示当前页的前4页和当前页的后5页。
* 但是这里又有两种情况:如果总共有11页,当前页是3,则3-4=-1,这是不可以的,
* 即当前面的页面少于4个时,这个时候显示前十页。
* 同理:当后面的页面不足5个时,显示后10页。
*/
if (pageCount<=10) {
beginPageIndex=1;
endPageIndex=pageCount;
}else{
beginPageIndex=currentPage-4;
endPageIndex=currentPage+5;
if (beginPageIndex-4<1) {
beginPageIndex=1;
endPageIndex=10;
}
if (endPageIndex>pageCount) {
beginPageIndex=currentPage-10+1;
endPageIndex=pageCount;
}
}
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public List getRecordList() {
return recordList;
}
public void setRecordList(List recordList) {
this.recordList = recordList;
}
public int getRecordCount() {
return recordCount;
}
public void setRecordCount(int recordCount) {
this.recordCount = recordCount;
}
public int getPageCount() {
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
public int getBeginPageIndex() {
return beginPageIndex;
}
public void setBeginPageIndex(int beginPageIndex) {
this.beginPageIndex = beginPageIndex;
}
public int getEndPageIndex() {
return endPageIndex;
}
public void setEndPageIndex(int endPageIndex) {
this.endPageIndex = endPageIndex;
}
}
//因为页面是要获取的是关于分页的pageBean这个类,页面获取里面的值,所以这里要想办法查询出pageBean这里面的字段的值
@Override
public PageBean getPageBeanByTopic(int pageNum, int pageSize, Topic topic) {
List list=getSession().createQuery(//
"FROM Reply r WHERE r.topic= ? ORDER BY r.postTime ")
.setParameter(0,topic)
.setFirstResult((pageNum-1)*10)
.setMaxResults(pageSize)
.list();
Long count=(Long) getSession().createQuery(
"SELECT COUNT(*) FROM Reply r WHERE r.topic= ? ")
.setParameter(0,topic)
.uniqueResult();
return new PageBean(pageNum, pageSize, list, count.intValue());
}
步骤应该是这样:先分析了类的字段,然后从数据库中查询中部分字段,然后将部分字段带入公式计算剩下的字段。
这里使用了根据部分字段来写构造方法,然后service在调用这个构造方法,计算公式。
看下jsp页面的代码:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<html>
<head>
<title>查看主题:${topic.title}</title>
<%@ include file="/WEB-INF/jsp/public/commons.jspf" %>
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/style/blue/forum.css" />
<script language="javascript" src="${pageContext.request.contextPath}/script/fckeditor/fckeditor.js" charset="utf-8"></script>
<script type="text/javascript">
$(function(){
var fck = new FCKeditor("content");
fck.Width = "90%";
fck.ToolbarSet = "bbs";
fck.BasePath = "${pageContext.request.contextPath}/script/fckeditor/";
fck.ReplaceTextarea();
});
</script>
</head>
<body>
<!-- 标题显示 -->
<div id="Title_bar">
<div id="Title_bar_Head">
<div id="Title_Head"></div>
<div id="Title"><!--页面标题-->
<img border="0" width="13" height="13" src="${pageContext.request.contextPath}/style/images/title_arrow.gif"/> 查看主题
</div>
<div id="Title_End"></div>
</div>
</div>
<!--内容显示-->
<div id="MainArea">
<div id="PageHead"></div>
<center>
<div class="ItemBlock_Title1" style="width: 98%">
<font class="MenuPoint"> > </font>
<s:a action="forum_list">论坛</s:a>
<font class="MenuPoint"> > </font>
<s:a action="forum_show?id=%{#topic.forum.id}">${topic.forum.name}</s:a>
<font class="MenuPoint"> >> </font>
帖子阅读
<span style="margin-left:30px;">
<s:a action="topic_addUI?forumId=%{#topic.forum.id}">
<img align="absmiddle" src="${pageContext.request.contextPath}/style/blue/images/button/publishNewTopic.png"/>
</s:a>
</span>
</div>
<div class="ForumPageTableBorder dataContainer" datakey="replyList">
<!--显示主题标题等-->
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr valign="bottom">
<td width="3" class="ForumPageTableTitleLeft"> </td>
<td class="ForumPageTableTitle"><b>本帖主题:${topic.title}</b></td>
<td class="ForumPageTableTitle" align="right" style="padding-right:12px;">
<s:a cssClass="detail" action="reply_addUI?topicId=%{#topic.id}">
<img border="0" src="${pageContext.request.contextPath}/style/images/reply.gif" />
回复
</s:a>
<a href="moveUI.html"><img border="0" src="${pageContext.request.contextPath}/style/images/edit.gif" />移动到其他版块</a>
<a href="#" onClick="return confirm('要把本主题设为精华吗?')"><img border="0" src="${pageContext.request.contextPath}/style/images/topicType_1.gif" />精华</a>
<a href="#" onClick="return confirm('要把本主题设为置顶吗?')"><img border="0" src="${pageContext.request.contextPath}/style/images/topicType_2.gif" />置顶</a>
<a href="#" onClick="return confirm('要把本主题设为普通吗?')"><img border="0" src="${pageContext.request.contextPath}/style/images/topicType_0.gif" />普通</a>
</td>
<td width="3" class="ForumPageTableTitleRight"> </td>
</tr>
<tr height="1" class="ForumPageTableTitleLine"><td colspan="4"></td></tr>
</table>
<!-- ~~~~~~~~~~~~~~~ 显示主帖(主帖只在第1页显示) ~~~~~~~~~~~~~~~ -->
<s:if test="currentPage==1">
<div class="ListArea">
<table border="0" cellpadding="0" cellspacing="1" width="100%">
<tr>
<td rowspan="3" width="130" class="PhotoArea" align="center" valign="top">
<!--作者头像-->
<div class="AuthorPhoto">
<img border="0" width="110" height="110" src="${pageContext.request.contextPath}/style/images/defaultAvatar.gif"
onerror="this.onerror=null; this.src='${pageContext.request.contextPath}/style/images/defaultAvatar.gif';" />
</div>
<!--作者名称-->
<div class="AuthorName">${topic.author.name}</div>
</td>
<td align="center">
<ul class="TopicFunc">
<!--操作列表-->
<li class="TopicFuncLi">
<a class="detail" href="${pageContext.request.contextPath}/BBS_Topic/saveUI.html"><img border="0" src="${pageContext.request.contextPath}/style/images/edit.gif" />编辑</a>
<a class="detail" href="#" onClick="return confirm('确定要删除本帖吗?')"><img border="0" src="${pageContext.request.contextPath}/style/images/delete.gif" />删除</a>
</li>
<!-- 文章的标题 -->
<li class="TopicSubject">
${topic.title}
</li>
</ul>
</td>
</tr>
<tr><!-- 文章内容 -->
<td valign="top" align="center">
<div class="Content">${topic.content}</div>
</td>
</tr>
<tr><!--显示楼层等信息-->
<td class="Footer" height="28" align="center" valign="bottom">
<ul style="margin: 0px; width: 98%;">
<li style="float: left; line-height:18px;"><font color=#C30000>[楼主]</font>
${topic.postTime}
</li>
<li style="float: right;"><a href="javascript:scroll(0,0)">
<img border="0" src="${pageContext.request.contextPath}/style/images/top.gif" /></a>
</li>
</ul>
</td>
</tr>
</table>
</div>
</s:if>
<!-- ~~~~~~~~~~~~~~~ 显示主帖结束 ~~~~~~~~~~~~~~~ -->
<!-- ~~~~~~~~~~~~~~~ 显示回复列表 ~~~~~~~~~~~~~~~ -->
<s:iterator value="recordList" status="status">
<div class="ListArea template">
<table border="0" cellpadding="0" cellspacing="1" width="100%">
<tr>
<td rowspan="3" width="130" class="PhotoArea" align="center" valign="top">
<!--作者头像-->
<div class="AuthorPhoto">
<img border="0" width="110" height="110" src="${pageContext.request.contextPath}/style/images/defaultAvatar.gif"
onerror="this.onerror=null; this.src='${pageContext.request.contextPath}/style/images/defaultAvatar.gif';" />
</div>
<!--作者名称-->
<div class="AuthorName">${author.name}</div>
</td>
<td align="center">
<ul class="TopicFunc">
<!--操作列表-->
<li class="TopicFuncLi">
<a class="detail" href="${pageContext.request.contextPath}/BBS_Topic/saveUI.html"><img border="0" src="${pageContext.request.contextPath}/style/images/edit.gif" />编辑</a>
<a class="detail" href="#" onClick="return confirm('确定要删除本帖吗?')"><img border="0" src="${pageContext.request.contextPath}/style/images/delete.gif" />删除</a>
</li>
<!-- 文章表情与标题 -->
<li class="TopicSubject">
${title}
</li>
</ul>
</td>
</tr>
<tr><!-- 文章内容 -->
<td valign="top" align="center">
<div class="Content">${content}</div>
</td>
</tr>
<tr><!--显示楼层等信息-->
<td class="Footer" height="28" align="center" valign="bottom">
<ul style="margin: 0px; width: 98%;">
<li style="float: left; line-height:18px;"><font color=#C30000>[${(currentPage-1)*pageSize + status.count}楼]</font>
${postTime}
</li>
<li style="float: right;"><a href="javascript:scroll(0,0)">
<img border="0" src="${pageContext.request.contextPath}/style/images/top.gif" /></a>
</li>
</ul>
</td>
</tr>
</table>
</div>
</s:iterator>
<!-- ~~~~~~~~~~~~~~~ 显示回复列表结束 ~~~~~~~~~~~~~~~ -->
</div>
<!--分页信息-->
<div id=PageSelectorBar>
<div id=PageSelectorMemo>
页次:${currentPage}/ ${pageCount} 页
每页显示:${pageSize}条
总记录数:${recordCount}条
</div>
<div id=PageSelectorSelectorArea>
<a href="javascript:gotoPage(1)" title="首页" style="cursor: hand;">
<img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png"/>
</a>
<!-- 注意EL表达式是用在外面,OGNL表达式是用在struts标签的内部,标签内 -->
<s:iterator begin="%{beginPageIndex}" end="%{endPageIndex}" var="num" >
<!-- var属性的对象的值存在了map中,所以用#获取-->
<s:if test="#num==currentPage">
<span class="PageSelectorNum PageSelectorSelected">${num}</span>
</s:if>
<!-- 非当前页 -->
<s:else>
<span class="PageSelectorNum" style="cursor: hand;" onClick="gotoPage(${num});">${num}</span>
</s:else>
</s:iterator>
<a href="javascript:gotoPage(${pageCount})" title="尾页" style="cursor: hand;">
<img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png"/>
</a>
转到:
<select onchange="gotoPage(this.value)" id="_pn" >
<s:iterator begin="1" end="%{pageCount}" var="num">
<option value="${num}">${num}</option>
</s:iterator>
</select>
<script type="text/javascript">
$("#_pn").val("${currentPage}");
</script>
</div>
</div>
<!-- 这里有问题,页面跳转不过来 -->
<script type="text/javascript">
function gotoPage(pageNum){
window.location.href="topic_show.action?id=${id}&pageNum="+pageNum;
}
</script>
<div class="ForumPageTableBorder" style="margin-top: 25px;">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr valign="bottom">
<td width="3" class="ForumPageTableTitleLeft"> </td>
<td class="ForumPageTableTitle"><b>快速回复</b></td>
<td width="3" class="ForumPageTableTitleRight"> </td>
</tr>
<tr height="1" class="ForumPageTableTitleLine">
<td colspan="3"></td>
</tr>
</table>
</div>
</center>
<!--快速回复-->
<div class="QuictReply">
<form action="">
<div style="padding-left: 3px;">
<table border="0" cellspacing="1" width="98%" cellpadding="5" class="TableStyle">
<tr height="30" class="Tint">
<td width="50px" class="Deep"><b>标题</b></td>
<td class="no_color_bg">
<input type="text" name="title" class="InputStyle" value="回复:昨天发现在表单里删除的图片" style="width:90%"/>
</td>
</tr>
<tr class="Tint" height="200">
<td valign="top" rowspan="2" class="Deep"><b>内容</b></td>
<td valign="top" class="no_color_bg">
<textarea name="content" style="width: 95%; height: 300px"></textarea>
</td>
</tr>
<tr height="30" class="Tint">
<td class="no_color_bg" colspan="2" align="center">
<input type="image" src="${pageContext.request.contextPath}/style/blue/images/button/submit.PNG" style="margin-right:15px;"/>
</td>
</tr>
</table>
</div>
</form>
</div>
</div>
<div class="Description">
说明:<br />
1,主帖只在第一页显示。<br />
2,只有是管理员才可以进行“移动”、“编辑”、“删除”、“精华”、“置顶”的操作。<br />
3,删除主帖,就会删除所有的跟帖(回复)。<br />
</div>
</body>
</html>

浙公网安备 33010602011771号