为
我们的项目写的一个轻量的分页API。目的在于将分页与数据查询的逻辑完全剥离。我以前看过robbin发的通过detachedCriteria实现的
分页那片贴子,里面把分页和数据查询结合在一起了。而我觉得分开更轻量,而且替换也比较容易。但是这个实现中有一个反模式,在逻辑中生成了代码,无奈之
选,为了简便。其中字符生成可以自己扩展i18n实现,应该非常容易。
分页实现的接口:
package com.goldnet.framework.util.paging;


/** *//**
* 分页操作的接口
* @author Tin
*/

public interface IPagination
{


/** *//**
* 默认的分页大小
*/
public static final int DEFAULT_PAGE_SIZE = 15;


/** *//**
* 默认的分页参数,指URL中用到的参数名
*/
public static final String PAGE_SIZE_KEY = "pageSize";


/** *//**
* 默认的页码参数,指URL中用到的参数名
*/
public static final String PAGE_NO_KEY = "pageno";


/** *//**
* 获取总页数
* @return 总页数
*/
int getPageSum();


/** *//**
* 下一页的页码
* @return
*/
int getNextPageNo();


/** *//**
* 上一页的页码
* @return
*/
int getPrevPageNo();


/** *//**
* 是否有下一页,即是否为最后一页
* @return 是否有下一页
*/
boolean hasNextPage();


/** *//**
* 是否有上一页,即是否为第一页
* @return 是否有上一页
*/
boolean hasPrevPage();


/** *//**
* 添加参数名称、值对,如果页面需要使用parameters传递分页外的附加参数
* @param parameterName 参数名
* @param parameterValue 参数值
*/
void addPageParameter(String parameterName, String parameterValue);

String getPageUrl();

String getPageHtmlStr();

int getItemSum();

void setItemSum(int itemSum);

String getPageExtension();

void setPageExtension(String pageExtension);

String getPageName();

void setPageName(String pageName);

int getPageNo();

void setPageNo(int pageNo);

int getPageSize();

void setPageSize(int pageSize);

}抽象基类:

/** *//**
*
*/
package com.goldnet.framework.util.paging;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;



/** *//**
* 对PagingString的重构
* @author Tin
*
*/

public abstract class AbstractPagination implements IPagination
{

/** *//**
* Page上显示的List中的domainModel的总数
*/
protected int itemSum = -1;


/** *//**
* 分页的大小
*/
protected int pageSize = DEFAULT_PAGE_SIZE;


/** *//**
* 页数
*/
protected int pageNo = 0;


/** *//**
* 分页的页面的相对URL,不包括后缀
*/
protected String pageName = null;


/** *//**
* 页面的URL的后缀
*/
protected String pageExtension = ".action";


/** *//**
* 参数列表
*/
protected List<PageParameter> parameterList = new LinkedList<PageParameter>();


/** *//**
* 返回的分页信息的字符串
*/
protected String pageHtmlStr = null;


/** *//**
* 默认的构造函数
* @param pageName 分页的页面的相对URL,不包括后缀
* @param pageExtension 页面的URL的后缀
* @param itemSum Page上显示的List中的domainModel的总数
* @param pageNo 页数
* @param pageSize 分页的大小
*/
public AbstractPagination(String pageName, String pageExtension,

int itemSum, int pageNo, int pageSize)
{
super();

this.pageName = pageName;
this.pageExtension = pageExtension;
this.itemSum = itemSum;
this.pageNo = pageNo;
this.pageSize = pageSize;
}


/** *//**
* 无PageSize构造函数,使用默认PageSize为15
* @param pageName 分页的页面的相对URL,不包括后缀
* @param pageExtension 页面的URL的后缀
* @param itemSum Page上显示的List中的domainModel的总数
* @param pageNo 页数
*/
public AbstractPagination(String pageName, String pageExtension,

int itemSum, int pageNo)
{
super();

this.pageName = pageName;
this.pageExtension = pageExtension;
this.itemSum = itemSum;
this.pageNo = pageNo;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPageSum()
*/

public int getPageSum()
{

if ((itemSum != -1) && (pageSize > 0))
{
return ((itemSum % pageSize) == 0) ? (itemSum / pageSize)
: ((itemSum / pageSize) + 1);
}

return 0;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getNextPageNo()
*/

public int getNextPageNo()
{
return (pageNo < (getPageSum() - 1)) ? (pageNo + 1) : (getPageSum() -
1);
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPrevPageNo()
*/

public int getPrevPageNo()
{
return (pageNo > 0) ? (pageNo - 1) : 0;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#hasNextPage()
*/

public boolean hasNextPage()
{

if (getPageSum() <= pageNo)
{
return false;
}

return true;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#hasPrevPage()
*/

public boolean hasPrevPage()
{

if (pageNo <= 0)
{
return false;
}

return true;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#addPageParameter(java.lang.String, java.lang.String)
*/

public void addPageParameter(String parameterName, String parameterValue)
{
PageParameter pp = new PageParameter(parameterName, parameterValue);
this.parameterList.add(pp);
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPageUrl()
*/

public String getPageUrl()
{
String url = pageName + pageExtension;


if (parameterList.size() > 0)
{
Iterator<PageParameter> iterator = parameterList.iterator();
PageParameter pageFirstParameter = iterator.next();
url += ("?" + pageFirstParameter.getParameterName() + "=" +
pageFirstParameter.getParameterValue());


while (iterator.hasNext())
{
PageParameter pageParameter = iterator.next();
url += ("&" + pageParameter.getParameterName() + "=" +
pageParameter.getParameterValue());
}

} else
{
//补充一个?解决附加分页参数时无?的问题
url += "?";
}


if (pageSize != DEFAULT_PAGE_SIZE)
{
url += ("&" + PAGE_SIZE_KEY + "=" + pageSize);
}

return url;
}


/** *//**
* 子类必须覆盖的方法,用来计算分页的字符的方法
*/
public abstract void compilePaginationString();


/** *//**
* Getters & Setters
*/


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPageHtmlStr()
*/

public String getPageHtmlStr()
{
compilePaginationString();

return pageHtmlStr;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getItemSum()
*/

public int getItemSum()
{
return itemSum;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#setItemSum(int)
*/

public void setItemSum(int itemSum)
{
this.itemSum = itemSum;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPageExtension()
*/

public String getPageExtension()
{
return pageExtension;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#setPageExtension(java.lang.String)
*/

public void setPageExtension(String pageExtension)
{
this.pageExtension = pageExtension;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPageName()
*/

public String getPageName()
{
return pageName;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#setPageName(java.lang.String)
*/

public void setPageName(String pageName)
{
this.pageName = pageName;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPageNo()
*/

public int getPageNo()
{
return pageNo;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#setPageNo(int)
*/

public void setPageNo(int pageNo)
{
this.pageNo = pageNo;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#getPageSize()
*/

public int getPageSize()
{
return pageSize;
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.IPagination#setPageSize(int)
*/

public void setPageSize(int pageSize)
{
this.pageSize = pageSize;
}


public List<PageParameter> getParameterList()
{
return parameterList;
}


public void setParameterList(List<PageParameter> parameterList)
{
this.parameterList = parameterList;
}


/** *//**
* 分页参数,页面的QueryString形式都是?parameter=value的形式,此处为一对
* 数据的抽象
* @author Tin
*
*/

private class PageParameter
{

/** *//**
* 参数名称
*/
private String parameterName;


/** *//**
* 参数值
*/
private String parameterValue;


/** *//**
* 唯一构造函数
* @param parameterName 参数名称
* @param parameterValue 参数值
*/

public PageParameter(String parameterName, String parameterValue)
{
this.parameterName = parameterName;
this.parameterValue = parameterValue;
}


public String getParameterName()
{
return parameterName;
}


public String getParameterValue()
{
return parameterValue;
}
}
} 默认的分页实现:
package com.goldnet.framework.util.paging;



/** *//**
* 默认的分页实现
* @author Tin
*
*/

public class DefaultPagination extends AbstractPagination
{

/** *//**
* 默认的构造函数
* @param pageName 分页的页面的相对URL,不包括后缀
* @param pageExtension 页面的URL的后缀
* @param itemSum Page上显示的List中的domainModel的总数
* @param pageNo 页数
* @param pageSize 分页的大小
*/
public DefaultPagination(String pageName, String pageExtension,

int itemSum, int pageNo, int pageSize)
{
super(pageName, pageExtension, itemSum, pageNo, pageSize);
}


/** *//**
* 无PageSize构造函数,使用默认PageSize为15
* @param pageName 分页的页面的相对URL,不包括后缀
* @param pageExtension 页面的URL的后缀
* @param itemSum Page上显示的List中的domainModel的总数
* @param pageNo 页数
*/
public DefaultPagination(String pageName, String pageExtension,

int itemSum, int pageNo)
{
super(pageName, pageExtension, itemSum, pageNo);
}

@Override

public void compilePaginationString()
{
String pageUrl = getPageUrl();
pageHtmlStr = "\u5171 " + itemSum + " \u6761 \u7b2c " +
(pageNo + 1) + " \u9875 / \u5171 " + getPageSum() +
" \u9875 <a href=\"" + pageUrl + "&" + PAGE_NO_KEY +
"=0\">\u9996\u9875</a> <a href=\"" + pageUrl + "&" +
PAGE_NO_KEY + "=" + getPrevPageNo() +
"\">\u4e0a\u4e00\u9875</a> <a href=\"" + pageUrl + "&" +
PAGE_NO_KEY + "=" + getNextPageNo() +
"\">\u4e0b\u4e00\u9875</a> <a href=\"" + pageUrl + "&" +
PAGE_NO_KEY + "=" + (getPageSum() - 1) +
"\">\u5c3e\u9875</a> \u6bcf\u9875\u663e\u793a" +
pageSize + "\u6761";
}
}

数字风格的实现:

/** *//**
*
*/
package com.goldnet.framework.util.paging;



/** *//**
* 数字页码风格的分页实现
* @author Tin
*
*/

public class PageNumberPagination extends AbstractPagination
{

/** *//**
* 默认的构造函数
* @param pageName 分页的页面的相对URL,不包括后缀
* @param pageExtension 页面的URL的后缀
* @param itemSum Page上显示的List中的domainModel的总数
* @param pageNo 页数
* @param pageSize 分页的大小
*/
public PageNumberPagination(String pageName, String pageExtension,

int itemSum, int pageNo, int pageSize)
{
super(pageName, pageExtension, itemSum, pageNo, pageSize);
}


/** *//**
* 无PageSize构造函数,使用默认PageSize为15
* @param pageName 分页的页面的相对URL,不包括后缀
* @param pageExtension 页面的URL的后缀
* @param itemSum Page上显示的List中的domainModel的总数
* @param pageNo 页数
*/
public PageNumberPagination(String pageName, String pageExtension,

int itemSum, int pageNo)
{
super(pageName, pageExtension, itemSum, pageNo);
}


/**//* (non-Javadoc)
* @see com.goldnet.framework.util.paging.AbstractPagination#compilePaginationString()
*/
@Override

public void compilePaginationString()
{
String pageUrl = getPageUrl();
StringBuffer returnString = new StringBuffer();
returnString.append("\u5171 " + itemSum + " \u6761 \u7b2c " +
(pageNo + 1) + " \u9875 / \u5171 " + getPageSum() +
" \u9875 <a href=\"" + pageUrl + "&" + PAGE_NO_KEY + "=" +
getPrevPageNo() + "\"><<</a> ");


for (int page = 0; page < getPageSum(); page++)
{

if(page!=pageNo)
{
returnString.append("<a href=\""+pageUrl +"&"+PAGE_NO_KEY + "=" + page +"\">"+(page+1)+"</a> ");

} else
{
returnString.append("<a href=\""+pageUrl +"&"+PAGE_NO_KEY + "=" + page +"\"><span style=\"background:black;color:#eee;font-size:120%;padding-left:5px;padding-right:5px;text-align:center;\">"+(page+1)+"</span></a> ");
}
}

returnString.append(" <a href=\"" + pageUrl + "&" +
PAGE_NO_KEY + "=" + getNextPageNo() +
"\">>></a> \u6bcf\u9875\u663e\u793a" + pageSize +
"\u6761");
pageHtmlStr = returnString.toString();
}
}

测试类,用的JUnit3,其实JUnit4更优雅:D
package com.goldnet.test.unittest.framework.paging;

import junit.framework.TestCase;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.goldnet.framework.util.paging.DefaultPagination;
import com.goldnet.framework.util.paging.IPagination;
import com.goldnet.framework.util.paging.PageNumberPagination;


public class TestPagination extends TestCase
{
protected transient final Log log = LogFactory.getLog(getClass());


protected void setUp() throws Exception
{
super.setUp();
}


protected void tearDown() throws Exception
{
super.tearDown();
}


public void testDefaultPainationWith3Parameters()
{
IPagination p = new DefaultPagination("test",".action",50,2);
p.addPageParameter("a","b");
p.addPageParameter("c","234");
p.addPageParameter("e.ddd","34234adbb");
log.info(p.getPageHtmlStr());
}

public void testDefaultPainationWith1Parameters()
{
IPagination p = new DefaultPagination("test",".action",50,2);
p.addPageParameter("a","b");
log.info(p.getPageHtmlStr());
}

public void testDefaultPainationWithNoParameters()
{
IPagination p = new DefaultPagination("test",".action",50,2);
log.info(p.getPageHtmlStr());
}

public void testDefaultPainationWith3ParametersAndCustomPageSize()
{
IPagination p = new DefaultPagination("test",".action",50,2,5);
p.addPageParameter("a","b");
p.addPageParameter("c","234");
p.addPageParameter("e.ddd","34234adbb");
log.info(p.getPageHtmlStr());
}

public void testDefaultPainationWithNoParametersAndCustomPageSize()
{
IPagination p = new DefaultPagination("test",".action",50,2,5);
log.info(p.getPageHtmlStr());
}

public void testPageNumberPainationWith3Parameters()
{
IPagination p = new PageNumberPagination("test",".action",50,2);
p.addPageParameter("a","b");
p.addPageParameter("c","234");
p.addPageParameter("e.ddd","34234adbb");
log.info(p.getPageHtmlStr());
}

public void testPageNumberPainationWith1Parameters()
{
IPagination p = new PageNumberPagination("test",".action",50,2);
p.addPageParameter("a","b");
log.info(p.getPageHtmlStr());
}

public void testPageNumberPainationWithNoParameters()
{
IPagination p = new PageNumberPagination("test",".action",50,2);
log.info(p.getPageHtmlStr());
}

public void testPageNumberPainationWith3ParametersAndCustomPageSize()
{
IPagination p = new PageNumberPagination("test",".action",50,2,5);
p.addPageParameter("a","b");
p.addPageParameter("c","234");
p.addPageParameter("e.ddd","34234adbb");
log.info(p.getPageHtmlStr());
}

public void testPageNumberPainationWithNoParametersAndCustomPageSize()
{
IPagination p = new PageNumberPagination("test",".action",50,2,5);
log.info(p.getPageHtmlStr());
}
}

说实话这么丑陋的东西本不愿意现眼……但是实在没什么可发的,应朋友所托共享出来。
特
点就是分页逻辑不管你用hibernate、JDBC、iBatis或者什么其他的,都可以和它一起工作,因为我任为对于DAO或者Action来说分页
逻辑就应该是pageSize、Pageno、itemSum这几个参数的传递,具体的显示上的问题应该交给第三方来负责,如taglib什么的,所以才
写了这样的实现。而且这个实现应该容易扩展。配合js跳转(css也应该抽出)等可以实现更多风格:D
posted on 2006-04-01 18:06
SIMONE 阅读(304)
评论(0) 编辑 收藏 所属分类:
JSP