之前一直認為分頁是很繁瑣的事情,隨着時間的積累,這一次再次接觸到分頁功能,思路清晰了許多,其實分頁無非就是根據頁面的顯示信息獲取分頁的幾個值,大體上這些值也可以分類的:
比如:頁面傳遞的值或者默認的值;通過查詢數據庫的內容來獲取的值;通過推導公式計算出來的值。
(其實推導都是很簡單的,只不過一提公式腦袋就大了,這是典型的不動腦的習慣,我本人屬於此類,呵呵,所以大家還是多動腦,動腦,腦袋越動越靈活。)
下面我們分析關於分頁所需要哪些內容:其實基本上所有網頁的分頁都是大同小異的,或許我們有時候會有很多分頁工具封裝好了這些分頁內容,比如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>