Posted on 2006-11-26 13:25
帥子 閱讀(181)
評(píng)論(0) 編輯 收藏 所屬分類:
j2se技術(shù)專區(qū)
到分頁(yè)算法,一般WEB開(kāi)發(fā)都會(huì)用到,我只是在我的實(shí)現(xiàn)技術(shù)上用了struts框架,其實(shí)原理都一樣的。
看了網(wǎng)上相當(dāng)多的分頁(yè)算法,有對(duì)的也有好多是錯(cuò)的,更有好多是不太優(yōu)化的。還有以前自己在augmentum做的一個(gè)分頁(yè)算法,總結(jié)了一些不足。決定重新再寫(xiě)一個(gè)分頁(yè)算法。
首先,應(yīng)該寫(xiě)個(gè)bean來(lái)記錄存儲(chǔ)一些頁(yè)面的屬性
分頁(yè)大致需要如下屬性:
?private?int?currentPage?=?1;?//?當(dāng)前頁(yè)
?private?int?totalPages?=?0;?//?總頁(yè)數(shù)
?private?int?pageRecorders?=?5;//?每頁(yè)5條數(shù)據(jù)?
?private?int?totalRows?=?0;?//?總數(shù)據(jù)數(shù)
?private?int?pageStartRow?=?0;//?每頁(yè)的起始數(shù)
?private?int?pageEndRow?=?0;?//?每頁(yè)顯示數(shù)據(jù)的終止數(shù)
?private?boolean?hasNextPage?=?false;?//?是否有下一頁(yè)
?private?boolean?hasPreviousPage?=?false;?//?是否有前一頁(yè)
?
?private?int?nextPage?=?0;//下一頁(yè)的頁(yè)碼
?
?private?int?previousPage?=?0;//上一頁(yè)的頁(yè)碼
然后這些屬性之間是有聯(lián)系的,我們可以在構(gòu)造函數(shù)的時(shí)候就初始化一些屬性
有兩種方法:
一,根據(jù)總的頁(yè)數(shù),(假設(shè)當(dāng)前頁(yè)為1)
?public?PageBean(int?totalRows){
??this.totalRows?=?totalRows;
??this.currentPage?=?1;
??hasPreviousPage?=?false;
??if?((totalRows?%?pageRecorders)?==?0)?{
???totalPages?=?totalRows?/?pageRecorders;
??}?else?{
???totalPages?=?totalRows?/?pageRecorders?+?1;
??}
??if?(totalRows?>=?pageRecorders)?{
???hasNextPage?=?true;
???nextPage?=?2;
???this.pageEndRow?=?pageRecorders;
??}?else?{
???this.pageEndRow?=?totalRows;
???hasNextPage?=?false;
???nextPage?=?1;
??}
???this.pageStartRow?=?0;??
???previousPage?=?1;
?}
然后在按下一頁(yè)或者上一頁(yè)的時(shí)候需要如下函數(shù)處理:
public?void?nextPage()?{
??if(hasNextPage?==?true)
??currentPage?=?currentPage?+?1;
??if?((currentPage?-?1)?>?0)?{
???hasPreviousPage?=?true;
??}?else?{
???hasPreviousPage?=?false;
??}
??if?(currentPage?>=?totalPages)?{
???hasNextPage?=?false;
???this.nextPage?=?currentPage;
??}?else?{
???hasNextPage?=?true;
???nextPage?=?currentPage+1;
??}
??this.pageStartRow?=?(currentPage?-1)?*?pageRecorders;
??if(hasNextPage?==?true)
??this.pageEndRow?=?pageStartRow?+?5;
??else{
???this.pageEndRow?=this.totalPages;
??}
??previousPage?=?currentPage?-?1;
?}
?
?public?void?previousPage()?{
??if(hasPreviousPage?==?true)
??currentPage?=?currentPage?-?1;
??if?(currentPage?==?0)?{
???currentPage?=?1;
??}
??if?(currentPage?>=?totalPages)?{
???hasNextPage?=?false;
??}?else?{
???hasNextPage?=?true;
??}
??nextPage?=?currentPage?+?1;
??if?((currentPage?-?1)?>?0)?{
???hasPreviousPage?=?true;
???previousPage?=?currentPage?-?1;
??}?else?{
???hasPreviousPage?=?false;
???previousPage?=?currentPage;
??}
??
??this.pageStartRow?=?(currentPage?-1)?*?pageRecorders;
??if(hasNextPage?==?true)
??this.pageEndRow?=?pageStartRow?+?5;
??else{
???this.pageEndRow?=this.totalPages;
??}
?}
在HTML中按下一頁(yè)或者上一頁(yè)的時(shí)候有如下代碼:
<logic:equal?name="page"?property="hasNextPage"?value="true">
<html:link?page="/List.do?action=nextPage">
nextPage
</html:link>
</logic:equal>
<logic:equal?name="page"?property="hasPreviousPage"?value="true">
<html:link?page="/List.do?action=previousPage">
PreviousPage
</html:link>
</logic:equal>
然后在Action中作如下處理:??
??String?currentPage?=?request.getParameter("currentPage");
??HttpSession?session?=?request.getSession();?
??EmployeeForm?employeeForm?=?(EmployeeForm)?form;
??String?queryString?=?null;
??String?queryCon?=?null;
??String?action?=?employeeForm.getAction();
??List?list?=?new?ArrayList();
??PageBean?pb?=?null;
??EmployeeDao?employeeDao?=?new?EmployeeDao();
??if(action?==?null?||?action.equals("null")){
???int?totalRows?=?employeeDao.getTotalRows();
??
????pb?=?new?PageBean(totalRows);
????session.removeAttribute("page");
????queryString?=?employeeForm.getQueryString();
????queryCon?=?employeeForm.getQueryCon();
????session.setAttribute("queryString",queryString);
????session.setAttribute("queryCon",queryCon);???
????list?=?employeeDao.getAllEmployee(queryString,?queryCon,
??????String.valueOf(pb.getPageStartRow()),
??????String.valueOf(pb.getPageRecorders()));
???????
??}else?if(action.equals("nextPage")){
???queryString?=?(String)session.getAttribute("queryString");
???queryCon?=?(String)session.getAttribute("queryCon");??????
???employeeForm.setQueryString(queryString);
???employeeForm.setQueryCon(queryCon);
???pb?=?(PageBean)session.getAttribute("page");
???pb.nextPage();
???list?=?employeeDao.getAllEmployee(queryString,?queryCon,
?????String.valueOf(pb.getPageStartRow()),
?????String.valueOf(pb.getPageRecorders()));
??}else?if(action.equals("previousPage")){
???queryString?=?(String)session.getAttribute("queryString");
???queryCon?=?(String)session.getAttribute("queryCon");
???employeeForm.setQueryString(queryString);
???employeeForm.setQueryCon(queryCon);
???pb?=?(PageBean)session.getAttribute("page");???
???pb.previousPage();
???list?=?employeeDao.getAllEmployee(queryString,?queryCon,
?????String.valueOf(pb.getPageStartRow()),
?????String.valueOf(pb.getPageRecorders()));
??}
????????
????????pb.description();
????????session.setAttribute("page",pb);????????
??request.setAttribute("admin",?"admin");
??request.setAttribute("employee",?list);
??return?mapping.findForward("showlist");
??然后在數(shù)據(jù)庫(kù)查詢中有如下代碼:
/**
*查詢總記錄數(shù)
*/
?public?int?getTotalRows()?{
??int?totalRows?=?0;
??String?sql?=?"select?count(*)?from?employee";//假設(shè)是員工表
??Database?db?=?new?Database();
??ResultSet?rs?=?db.executeQuery(sql);
??try?{
???while?(rs.next())?{
????String?id?=?(String)?rs.getString(1);
????totalRows?=?Integer.parseInt(id);
???}
??}?catch?(SQLException?e)?{
???e.printStackTrace();
??}
??db.close();
??return?totalRows;
?}
?
/*
*查詢每一頁(yè)需要查詢的頁(yè)碼
*/
public?List?getAllEmployee(String?queryString,?String?queryCon,String?startRow,String?num)?{
??List?list?=?new?ArrayList();
??String?sql?=?null;
??if?(queryString?==?null?||?queryString.equals(""))?{
???sql?=?"select?*?from?employee,dept?"?+
?????"where?dept.Id?=?employee.deptId?"?+
?????"order?by?employee.id?asc"+?"?limit?"+startRow+","+num;
??}?else?{
???sql?=?"select?*?from?employee,dept?"?+
?????"where?dept.Id?=?employee.deptId?order?by?employee."
?????+?queryString?+?"?"?+?queryCon?+?"?limit?"+startRow+","+num;
??}
??Employee?employee?=?null;
??Database?db?=?new?Database();
??ResultSet?rs?=?db.executeQuery(sql);
??try?{
???while?(rs.next())?{
????String?id?=?(String)?rs.getString("employee.id");
????String?name?=?(String)?rs.getString("employee.name");
????String?deptId?=?(String)?rs.getString("employee.deptId");
????String?deptName?=?(String)?rs.getString("dept.deptName");
????employee?=?new?Employee();
????employee.setId(id);
????employee.setName(name);
????employee.setDeptId(deptId);
????employee.setDeptName(deptName);
????list.add(employee);
???}
??}?catch?(SQLException?e)?{
???e.printStackTrace();
??}
??db.close();
??return?list;
?}
這里我用了hibernate進(jìn)行數(shù)據(jù)庫(kù)操作,你也可以用jdbc進(jìn)行操作,情況類似。
二,根據(jù)總的頁(yè)數(shù),當(dāng)前頁(yè)
這樣的話構(gòu)造函數(shù)應(yīng)該寫(xiě)成:
public?PageBean(int?totalRows,int?currentPage)?{
??this.totalRows?=?totalRows;
??this.currentPage?=?currentPage;
??if(currentPage?<?2)
???hasPreviousPage?=?false;
??else
???hasPreviousPage?=?true;
??if?((totalRows?%?pageRecorders)?==?0)?{
???totalPages?=?totalRows?/?pageRecorders;
??}?else?{
???totalPages?=?totalRows?/?pageRecorders?+?1;
??}
??if?(currentPage?<?totalPages)?{
???hasNextPage?=?true;
???nextPage?=?currentPage?+?1;
???pageStartRow?=?(currentPage?-?1)*pageRecorders;
???this.pageEndRow?=?pageStartRow?+?pageRecorders;
??}?else?if(currentPage?==?totalPages){
???pageStartRow?=?(currentPage?-?1)*pageRecorders;
???this.pageEndRow?=?totalRows;
???hasNextPage?=?false;
???nextPage?=?currentPage;
??}
??if(currentPage?<?2){
???previousPage?=?currentPage;
???hasPreviousPage?=?false;
??}else?if(currentPage?>?1){
???previousPage?=?currentPage-1;
???hasPreviousPage?=?true;
??}?
?}
在action中應(yīng)該寫(xiě)成
if(currentPage?==?null){
????pb?=?new?PageBean(totalRows);
????session.removeAttribute("page");
????queryString?=?employeeForm.getQueryString();
????queryCon?=?employeeForm.getQueryCon();
????session.setAttribute("queryString",queryString);
????session.setAttribute("queryCon",queryCon);???
????list?=?employeeDao.getAllEmployee(queryString,?queryCon,
??????String.valueOf(pb.getPageStartRow()),
??????String.valueOf(pb.getPageRecorders()));
????}
???else{
????pb?=?new?PageBean(totalRows,Integer.parseInt(currentPage));
????queryString?=?employeeForm.getQueryString();
????queryCon?=?employeeForm.getQueryCon();
????session.setAttribute("queryString",queryString);
????session.setAttribute("queryCon",queryCon);???
????list?=?employeeDao.getAllEmployee(queryString,?queryCon,
??????String.valueOf(pb.getPageStartRow()),
??????String.valueOf(pb.getPageRecorders()));
???}
??session.setAttribute("page",pb);????????
??request.setAttribute("admin",?"admin");
??request.setAttribute("employee",?list);
??return?mapping.findForward("showlist");
在jsp中應(yīng)該寫(xiě)成:
<logic:equal?name="page"?property="hasNextPage"?value="true">
<a?href="List.do?currentPage=<bean:write?name="page"?property="nextPage"/>">
nextPage
</a>
</logic:equal>
<logic:equal?name="page"?property="hasPreviousPage"?value="true">
?|?
<a?href="/test/List.do?currentPage=<bean:write?name="page"?property="previousPage"/>">
PreviousPage
</a>
</logic:equal>
數(shù)據(jù)庫(kù)查詢部分依然適用。
盡管洋洋灑灑貼了一部分代碼,不過(guò)好像不太想看,包括我,也比較討厭看一些煩瑣的代碼,所以如果你想要源代碼進(jìn)行探討研究的話,歡迎隨時(shí)找我。那就總結(jié)一下這兩種方法吧
首先這兩種方法都是取需要顯示的數(shù)據(jù)顯示,這樣,在數(shù)據(jù)庫(kù)龐大的情況下,比一次性把所有數(shù)據(jù)都取出來(lái)的效率要高。
第一種方法是把PageBean存在了一個(gè)HttpSession中,在進(jìn)入到顯示列表的時(shí)候就進(jìn)行了初始化,在jsp頁(yè)面?zhèn)鬟f的參數(shù)action是固定的三個(gè)值:null,nextPage,previousPage.這樣雖然比較容易理解,但是我發(fā)現(xiàn)一個(gè)BUG,就是如果你按刷新,他也會(huì)翻頁(yè),因?yàn)樗膗rl就是?.do?aciton=nextPage,這樣的話你傳進(jìn)去的action還是有一個(gè)值,這樣就會(huì)導(dǎo)致翻頁(yè)。
第二種方法是考慮了第一種方法的BUG,在jsp頁(yè)面?zhèn)鬟f的參數(shù)currentPage的值是bean中的nextPage的值或者previousPage里的值,用了struts標(biāo)簽庫(kù)嵌套,把值賦予currentPage,這樣的話currentPage的值是:1,2,3,4...totalPages之間。這樣的話你即使按刷新按鈕,他也是當(dāng)前頁(yè),因?yàn)樗膗rl就是.do?currentPage=someNumber(someNumber是1到totalPages中的一個(gè)值)。但是這樣的話Pagebean在每次訪問(wèn)的時(shí)候都要重新生成一個(gè)對(duì)象,該對(duì)象也是根據(jù)totalRows(總數(shù)據(jù)數(shù)),currentPage(當(dāng)前頁(yè)數(shù))進(jìn)行構(gòu)造,從而設(shè)置其他的一些屬性。個(gè)人比較推薦第二種方法。