我的分页类

把jdon的分页标签玩过之后该自己来实现完整的分页类了,同样一个需求:以CSS来完全控制分页的样式:
设计一个类叫CssPageBar(css分页条)


public class CssPageBar {
private int [] linkNums;

public int[] getLinkNums() {
return linkNums;
}

public void setLinkNums(int[] linkNums) {
this.linkNums = linkNums;
}

}

设计一个分页类Page

public class Page<T> {

private int pageNo = 1;//第几页
private int pageSize = 10;
//每页显示的记录数

private int totalCount;
//数据中记录的总条数

private List<T> result = new ArrayList<T>();
//每页需要显示的真实数据记录

private String orderBy = null;

private boolean asc = true;

private Map queryParams = new HashMap();
//封装页面的查询参数



//每页的第一条记录在结果集中的位置
public int getPageFirst(){
return ((pageNo - 1) * pageSize);
}


//总页数,这个是根据totalcount和pageSize计算的
public int getTotalPages(){
if (totalCount == 0)
return 0;

int count = totalCount / pageSize;
if (totalCount % pageSize > 0) {
count++;
}
return count;
}

/**
* 是否还有下一页.
*/

public boolean isHasNext() {
return (pageNo + 1 <= getTotalPages());
}

/**
* 返回下页的页号,序号从1开始.
*/

public int getNextPage() {
if (isHasNext())
return pageNo + 1;
else
return pageNo;
}

/**
* 是否还有上一页.
*/

public boolean isHasPre() {
return (pageNo - 1 >= 1);
}

/**
* 返回上页的页号,序号从1开始.
*/

public int getPrePage() {
if (isHasPre())
return pageNo - 1;
else
return pageNo;
}

/**
* 设置查询参数
*/

public void setQueryParam(String paramName, String paramValue){
this.queryParams.put(paramName, paramValue);
}

/**
*
* 多条件查询的URL参数
*/

public String getUrlParam() {
StringBuilder urlParam = new StringBuilder();
Map params = this.getQueryParams();
Iterator<String> keys = params.keySet().iterator();
if(params != null && keys.hasNext()){
String key = keys.next();
urlParam.append(key).append(
"=")
.append(params.get(key));
while(keys.hasNext()){
key = keys.next();
urlParam.append(
"&").append(key).append("=")
.append(params.get(key));
}
}
return urlParam.toString();
}
}

设计一个服务接口叫PaginationService

public interface PaginationService {
public CssPageBar process(Page page);
}

Action代码:


public void search(@Parameter(key = "author") String author,@Parameter(key = "fileName") String fileName){
page.setQueryParam(
"author", author);
page.setQueryParam(
"fileName", fileName);

page = uploadService.getUploadFiles(page);

cssPageBar = paginationService.process(page);
}

页面:
<div id="pagination" align="center" class="pagination">
<c:if test="${page.hasPre}"><a href="upload.search.logic?page.pageNo=${page.prePage}&${page.urlParam}">上一页</a></c:if>
<c:if test="${!page.hasPre}"><span class=disabled >上一页</span></c:if>

<c:forEach var="number" items="${cssPageBar.linkNums}">
<c:if test="${number == -1}"><span class="disabled">...</span></c:if>
<c:if test="${number == page.pageNo}"><span class="current"><c:out value="${page.pageNo}" /></span></c:if>
<c:if test="${number != -1 && number != page.pageNo}"><a href="upload.search.logic?page.pageNo=${number}&${page.urlParam}"/>${number}</a></c:if>
</c:forEach>

<c:if test="${page.hasNext}"><a href="upload.search.logic?page.pageNo=${page.nextPage}&${page.urlParam}"> 下一页</a></c:if>
<c:if test="${!page.hasNext}"><span class=disabled >下一页</span></c:if>
</div>

样式显示就看你的想象力了


[该贴被oojdon于2009-06-08 12:06修改过]




项目中的简单样式


挺漂亮的,多谢楼主分享

PaginationService的实现:


@Service("org.vraptor.spring.service.PaginationService")
public class PaginationService {
public static final int THRESHOLDFORELLIPSIS = 5;
// 分页链接a对象每组的显示个数

public CssPageBar process(Page page) {
int totalPage = page.getTotalPages();
int currentPage = page.getPageNo();
CssPageBar cssPageBar = new CssPageBar();
cssPageBar.setLinkNums(this.linkNums(totalPage, currentPage));
return cssPageBar;
}

private int[] linkNums(int totalPage, int currentPage) {
int[] pre = new int[0];
// 当前页的前组,包含当前页
int[] next = new int[0];
// 当前页的后组,不包含当前页

if (totalPage > 0) {
// 处理前组
if (currentPage <= THRESHOLDFORELLIPSIS) {
pre = new int[currentPage];
for (int i = 0; i < pre.length; i++) {
pre[i] = i + 1;
}
} else if (currentPage == totalPage) {
pre = new int[THRESHOLDFORELLIPSIS + 1];
pre[0] = 1;
pre[1] = 2;
pre[2] = -1;
pre[3] = currentPage - 2;
pre[4] = currentPage - 1;
pre[5] = currentPage;
} else {
pre = new int[THRESHOLDFORELLIPSIS];
pre[0] = 1;
pre[1] = 2;
pre[2] = -1;
pre[3] = currentPage - 1;
pre[4] = currentPage;
}
// 处理后组
if ((totalPage - currentPage) <= (THRESHOLDFORELLIPSIS - 1)) {
next = new int[totalPage - currentPage];
for (int i = 0; i < next.length; i++) {
next[i] = currentPage + i + 1;
}
} else if (currentPage == 1) {
next = new int[THRESHOLDFORELLIPSIS];
next[0] = 2;
next[1] = 3;
next[2] = -1;
next[3] = totalPage - 1;
next[4] = totalPage;
} else {
next = new int[THRESHOLDFORELLIPSIS - 1];
next[0] = currentPage + 1;
next[1] = -1;
next[2] = totalPage - 1;
next[3] = totalPage;
}
}

// 合并
int[] linkNums = new int[pre.length + next.length];

int index = 0;
for (int num : pre) {
linkNums[index++] = num;
}
for (int num : next) {
linkNums[index++] = num;
}

return linkNums;
}

}

从这个链接下载分页样式
http://www.jdon.com/jivejdon/thread/34031.html
[该贴被oojdon于2009-06-08 16:35修改过]

持久层用hibernate给分页对象填充每一页的数据


public Page<T> findPageList(Page<T> page, Criterion... criterion) {
Criteria c = createCriteria(criterion);

if (page.isOrderBySetted()) {
if (page.isAsc()) {
c.addOrder(Order.asc(page.getOrderBy()));
} else {
c.addOrder(Order.desc(page.getOrderBy()));
}
}

c.setFirstResult(page.getPageFirst());
c.setMaxResults(page.getPageSize());

page.setTotalCount(this.getTotalCount(criterion));
page.setResult(c.list());

return page;
}

public Page<T> findPageList(Page<T> page, Map criterionMap) {
Criteria c = this.getSession().createCriteria(persistClass);

if(criterionMap != null && !criterionMap.isEmpty()){
Set<String> keys = criterionMap.keySet();
for(String key : keys){
if(!("".equals(criterionMap.get(key)))
&& !(null == criterionMap.get(key)))
c.add(Restrictions.like(key, (String)criterionMap.get(key),MatchMode.ANYWHERE));

}
}

if (page.isOrderBySetted()) {
if (page.isAsc()) {
c.addOrder(Order.asc(page.getOrderBy()));
} else {
c.addOrder(Order.desc(page.getOrderBy()));
}
}

//获取根据条件分页查询的总行数
int totalCount = (Integer)c.setProjection(Projections.rowCount()).uniqueResult();
c.setProjection(null);

c.setFirstResult(page.getPageFirst());
c.setMaxResults(page.getPageSize());

page.setTotalCount(totalCount);
page.setResult(c.list());

return page;
}

public Criteria createCriteria(Criterion... criterions) {
Criteria criteria = getSession().createCriteria(persistClass);
for (Criterion c : criterions) {
criteria.add(c);
}
return criteria;
}

public int getTotalCount(Criterion... criterion){
Criteria c = createCriteria(criterion);
return (Integer)c.setProjection(Projections.rowCount()).uniqueResult();
}

请教楼主:div中的jstl表达式所使用的jstl的版本是多少?我使用jstl1.0和jstl1.1好像都有问题,分页的部分显示不出来, 但是page中的各项属性数值都是正确的.

<div id="pagination" align="center" class="pagination">
<c:if test="${page.hasPre}"><a href="upload.search.logic?page.pageNo=${page.prePage}&${page.urlParam}">上一页</a></c:if>
<c:if test="${!page.hasPre}"><span class=disabled >上一页</span></c:if>

<c:forEach var="number" items="${cssPageBar.linkNums}">
<c:if test="${number == -1}"><span class="disabled">...</span></c:if>
<c:if test="${number == page.pageNo}"><span class="current"><c:out value="${page.pageNo}" /></span></c:if>
<c:if test="${number != -1 && number != page.pageNo}"><a href="upload.search.logic?page.pageNo=${number}&${page.urlParam}"/>${number}</a></c:if>
</c:forEach>

<c:if test="${page.hasNext}"><a href="upload.search.logic?page.pageNo=${page.nextPage}&${page.urlParam}"> 下一页</a></c:if>
<c:if test="${!page.hasNext}"><span class=disabled >下一页</span></c:if>
</div>

div中的东西无法显示,请教了!

用了一下楼主的代码:
前端页面中我用jstl表达式计算<c:out value="${3+7}" />
可以得到结果是10, 证明我的jstl库是好的.
但是我如果取:<c:out value="${page.pageSize}" />
然后就取不到结果.我在action中用debug跟踪了page的结果
发现page.pageSize=3, 但是不知道为什么页面娶不到对应的结果, 我的action中的代码是:

我的action中的代码是:


// 在此输入java代码
public class OrderListAction extends Action {

public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) {

OrderService orderService = (OrderService) getAppContext().getBean(
"orderService");

//Collection orders = orderService.getOrders();
Page page = new Page();
page = orderService.getOrderPage(page);
Collection orders = page.getResult();
CssPageBar cssPageBar = new PaginationService().process(page);

System.out.println(orders);
CollectionForm collectionForm = (CollectionForm) actionForm;

System.out.println(page.getTotalPages());
collectionForm.setList(orders);
return actionMapping.findForward(
"forward");
}

private WebApplicationContext getAppContext() {
ServletContext servletContext = this.getServlet().getServletContext();
return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
}

}

还请oojdon大哥多多指教!

都出来了,谢谢分享!

那天有空了我把完整程序上传
我的框架是vraptor + spring +hibernate

大家一起贡献一下自己的分页实现以及分页思想!!

BTW:jdon的分页标签在多条件查询分页的时候怎么办?论坛首页那个时间排序箭头排序出来的结果点一下页就乱套了!
[该贴被oojdon于2009-06-10 23:41修改过]

分页的以前我和别人也一起做过,大致思想是用json格式充当一个http查询参数,像这样的
...?params={"eq":{"age":"10"},"like":{"name":"free"},"order":{"time":"asc","age":"desc"},"page":{"index":"2","size":"25"}}
这个参数可以由查询生成并传出到web,页面点击后由分页模板action解析成sql等进入查询,需要注意的有空值和0值问题。

>页标签在多条件查询分页的时候怎么办
我之前做的分页也是遇到了多条件查询分页查询的问题,
刚开始的处理是将查询参数传递到action中然后在action中
进行进行对应sql的拼装,然后传递作为查询条件传递到服务中,服务返回对应的查询结果.后来发现这种结果严重破坏了分层结构,将sql扩散到了action层.
然后就用了一个MAP进行参数与数值的封装, 然后通过服务传递到dao层中,在dao层对map中所封装的多条件参数解析拼装成
查询sql,然后执行查询返回结果.

我的分页做了一个通用的,然后在oracle,mysql,db2, sqlserver分别做了对应的分页程序,分页使用了数据库自带的分页机制,遇到那个数据库就用对应的分页.

楼上说的非常对,如果你在表现层就需要知道持久层的东西,那要OO干什么??下一层对上一层应该是完全黑盒的,这样才能保证业务变更的时候不会牵一发动全身。

>>下一层对上一层应该是完全黑盒的
一个page对象从表现层直达持久层,这样确实是一个问题啊
待深思,从新拿起领域驱动设计看一下,呵呵,谢谢楼上的