舉例詳解用Java實(shí)現(xiàn)web分頁功能的方法
分頁問題是一個(gè)非常普遍的問題,開發(fā)者幾乎都會(huì)遇到,這里不討論具體如何分頁,說明一下Web方式下分頁的原理。首先是查詢獲得一個(gè)結(jié)果集(表現(xiàn)為查詢數(shù)據(jù)庫獲得的結(jié)果),如果結(jié)果比較多我們一般都不會(huì)一下顯示所有的數(shù)據(jù),那么就會(huì)用分頁的方式來顯示某些數(shù)據(jù)(比如20條)。因?yàn)镠ttp的無狀態(tài)性,每一次提交都是當(dāng)作一個(gè)新的請求來處理,即使是換頁,上一次的結(jié)果對下一次是沒有影響的。
這里總結(jié)三種實(shí)現(xiàn)分頁的方式,不知道還有沒有別的!
1.每次取查詢結(jié)果的所有數(shù)據(jù),然后根據(jù)頁碼顯示指定的紀(jì)錄。
2.根據(jù)頁面只取一頁數(shù)據(jù),然后顯示這一頁,這里要構(gòu)造sql語句。
3.取一定頁數(shù)的數(shù)據(jù),就是前面兩種的折中。
這里還要注意的是這些數(shù)據(jù)是放在request還是session中,這里一一討論
1.一般不會(huì)放在session中,因?yàn)闀?huì)占用大量內(nèi)存,所以要放在request里面。
優(yōu)點(diǎn):實(shí)現(xiàn)比較簡單,查詢速度比較快。
缺點(diǎn):占用內(nèi)存多一些,網(wǎng)絡(luò)傳輸數(shù)據(jù)多。
對于數(shù)據(jù)量比較少的查詢這種方法比較合適。這里有人把數(shù)據(jù)放在session中,這樣換頁的時(shí)候就不用重新查詢,但是這樣是極其不好的,強(qiáng)烈建議不要這樣使用。
2.肯定不會(huì)放在session中,因?yàn)榉旁趕ession中沒有意義。
優(yōu)點(diǎn):占用內(nèi)存少。
缺點(diǎn):比較麻煩,必須先獲得查詢結(jié)果的總數(shù),因?yàn)橐烙卸嗌偌o(jì)錄才知道有多少頁。另外要構(gòu)造分頁查詢語句,對于不同的數(shù)據(jù)庫是不一樣的。
3.這種情況是肯定放在session中了,要不然我干嗎取好幾頁呀,這樣的實(shí)現(xiàn)是為了減少數(shù)據(jù)庫查詢的次數(shù),比如我保存第1到10的紀(jì)錄,那么換頁的時(shí)候如果在1到10之間就可以直接從session獲取。如果換到11頁,我可以重新設(shè)置緩存11到
20頁的數(shù)據(jù)(或者5到15頁的數(shù)據(jù)),這樣的話換10次才需要一次數(shù)據(jù)庫查詢操作。
優(yōu)點(diǎn):占用內(nèi)存相對不多,提高平均查詢速度。
缺點(diǎn):實(shí)現(xiàn)起來更加復(fù)雜,可能存在臟數(shù)據(jù),需要自己定義一個(gè)緩存集合。如果查詢的數(shù)據(jù)量比較大,可以考慮采用這樣方式。
下面的設(shè)計(jì)每次只獲取一頁數(shù)據(jù),每次都要重新設(shè)置查詢總數(shù),具體如何獲得自己實(shí)現(xiàn),這是一個(gè)比較通用的分頁實(shí)現(xiàn)。
這里設(shè)計(jì)一個(gè)接口:
package treeroot.util;
import java.util.List;
/**
* 該接口用來實(shí)現(xiàn)分頁功能,注意這里沒有提供修改的功能。
* @author treerot
* @version 1.0
* @since 2004-9-30
*/
public interface Pageable
{
/**
* 獲得數(shù)據(jù)結(jié)果
* @return
*/
public List getResult();
/**
* 獲得查詢總數(shù)
* @return
*/
public int getCount();
/**
* 獲得每頁紀(jì)錄數(shù)
* @return
*/
public int getPageSize();
/**
* 獲得當(dāng)前頁編號(hào)
* @return
*/
public int getCurrentPage();
/**
* 獲得總頁數(shù)
* @return
*/
public int getPages();
/**
* 每頁默認(rèn)顯示紀(jì)錄數(shù)
*/
public final static int DEFAULT_PAGESIZE=20;
}
這個(gè)接口非常簡單,就是包括一個(gè)結(jié)果列表和一些分頁的必要信息,這里注意幾點(diǎn):
1.這個(gè)接口的實(shí)現(xiàn)表示的是某一次查詢的某一頁數(shù)據(jù),和上次查詢無關(guān)
2.這個(gè)接口的實(shí)現(xiàn)應(yīng)該是只讀的,也就是說不可以修改的。
3.getPages()方法是冗余的,但是這里仍然提供這個(gè)方法。
下面給出一個(gè)抽象實(shí)現(xiàn):
package treeroot.util;
import java.util.List;
/**
* @author treerot
* @version 1.0
* @since 2004-9-30
*/
public abstract class AbstractPage implements Pageable
{
private int currentPage;
private int pageSize;
private int pages;
protected int count;
protected List result;
/**
* 指定當(dāng)前頁
* @param currentPage
* @throws PageException
*/
public AbstractPage(int currentPage){
this(currentPage,Pageable.DEFAULT_PAGESIZE);
}
/**
* 指定當(dāng)前頁和頁大小
* @param currentPage
* @param pageSize
* @throws PageException
*/
public AbstractPage(int currentPage,int pageSize) {
this.currentPage=currentPage;
this.pageSize=pageSize;
}
protected void checkPage(int currentPage) throws PageException{
if((currentPage<1)||(currentPage>this.getPages()))
throw new PageException("頁超出范圍:總頁數(shù)為"+this.getPages()+",當(dāng)前頁為"+currentPage);
}
/**
* 這個(gè)方法被子類重寫用來初始化,也就是計(jì)算count值和result結(jié)果,在子類 的構(gòu)造函數(shù)中調(diào)用。
*/
abstract protected void init() throws PageException;
public List getResult()
{
return result;
}
public int getCount()
{
return count;
}
public int getPageSize()
{
return pageSize;
}
public int getCurrentPage()
{
return currentPage;
}
public int getPages()
{
if(pages==0) this.pages=(count+pageSize-1)/pageSize;
return pages;
}
}
這個(gè)抽象類實(shí)現(xiàn)了接口中的所有方法,但是定義了一個(gè)抽象方法init(),在子類中必須實(shí)現(xiàn)這個(gè)方法。上面的一個(gè)接口和一個(gè)抽象類看起來比較簡單,你可能會(huì)覺得好像什么都沒有做,實(shí)現(xiàn)上確實(shí)沒有做什么,但是卻可以給開發(fā)帶來很大的幫助。我們可以根據(jù)自己的需要要繼承這個(gè)抽象類,而數(shù)據(jù)可以通過各種方式獲得,比如直接通過一個(gè)List獲得,或者通過JDBC,Hibernate等等,不過我們都需要把結(jié)果封裝到一個(gè)List里面,通過Hibernate就顯得特別方便了。
PageException是自定義的一個(gè)異常
package treeroot.util
/**
* @author treeroot
* @version 1.0
* @since 2004-9-30
*/
public class PageException extends Exception
{
public PageException(){
super();
}
public PageException(String message){
super(message);
}
}
相關(guān)文章
Springboot整個(gè)Quartz實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)的示例代碼
這篇文章主要介紹了Springboot整個(gè)Quartz實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09
Springboot上傳文件時(shí)提示405問題及排坑過程
這篇文章主要介紹了Springboot上傳文件時(shí)提示405問題及排坑過程,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Java實(shí)現(xiàn)將CSV轉(zhuǎn)為Excel的示例代碼
CSV(Comma?Separated?Values)文件是一種純文本文件,包含用逗號(hào)分隔的數(shù)據(jù),常用于將數(shù)據(jù)從一個(gè)應(yīng)用程序?qū)牖驅(qū)С龅搅硪粋€(gè)應(yīng)用程序。本文將利用Java實(shí)現(xiàn)CSV轉(zhuǎn)為Excel,感興趣的可以了解一下2022-03-03

