J2EE开发中少不了要用到分页的。在持久层Hibernate中已支持了原生的分页查找记录。为了便于开发高效的进行。现将开发中用到的记录下来。一起讨论讨论
方法一:
页面分页用标签的形式
页面标签处理
public class PageControllerTag extends BodyTagSupport {
private String gotoUrl;
private static final int DEFAULTPAGESIZE = Integer.parseInt(Constants.PAGE_DEFAULT_LIMIT);
public static final String TOTAL = "total";
private static final String PAGE_NO = "pageNo";
private static final String RECORD_COUNT = "pageSize";
@SuppressWarnings("unchecked")
@Override
public int doStartTag() throws JspException {
int pageNo = 1;
int total = 0;
int totalPage = 1;
HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
StringBuffer sb = new StringBuffer();
sb.append("\r\n<form method=\"post\" action=\"\"").append(
"name=\"pageController\">\r\n");
Enumeration enumeration = request.getParameterNames();
String name = null;
String value = null;
while (enumeration.hasMoreElements()) {
name = (String) enumeration.nextElement();
value = request.getParameter(name);
if (name.equals(RECORD_COUNT)) {
continue;
}
if (name.equals(PAGE_NO)) {
if (null != value && !"".equals(value)) {
pageNo = Integer.parseInt(value);
}
continue;
}
sb.append("<input type=\"hidden\" name=\"").append(name).
append("\" value=\"").append(value).append("\"/>\r\n");
}
sb.append("<input type='hidden' name=\"").append(PAGE_NO).append(
"\" value=\"").append(pageNo).append("\"/>\r\n");
String tot = (String)request.getAttribute(TOTAL);
if (null != tot && !"".equals(tot)) {
total = Integer.parseInt(tot);
}
totalPage = getTotalPage(total);
sb.append("<br/>\r\n");
sb.append(" \r\n");
sb.append("共").append(totalPage).append("页 当前第").
append(pageNo).append("页\r\n");
sb.append(" \r\n");
if (pageNo == 1) {
sb.append("首页");
sb.append(" ");
sb.append("上一页\r\n");
} else {
sb.append("<a href=\"#\" onclick=\"turnOverPage(1)\">首页</a>\r\n");
sb.append(" ");
sb.append("<a href=\"#\" onclick=\"turnOverPage('").append((pageNo - 1)).
append("')\">上一页</a>\r\n");
}
sb.append(" ");
if (pageNo == totalPage) {
sb.append("下一页");
sb.append(" ");
sb.append("尾页\r\n");
} else {
sb.append("<a href=\"#\" onclick=\"turnOverPage(").
append((pageNo + 1)).append(")\">下一页</a>\r\n");
sb.append(" ");
sb.append("<a href=\"#\" onclick=\"turnOverPage(").
append(totalPage).append(")\">尾页</a>\r\n");
}
sb.append(" ");
sb.append("跳转到<select onChange=\"turnOverPage(this.value)\">\r\n");
for (int i = 1; i <= totalPage; i++) {
if (i == pageNo) {
sb.append(" <option value=\"").append(i).
append("\" selected>第").append(i).append("页</option>\r\n");
} else {
sb.append(" <option value=\"").append(i).
append("\">第").append(i).append("页</option>\r\n");
}
}
sb.append("</select>\r\n");
sb.append(" \r\n");
sb.append("</form>\r\n");
sb.append("<script language=\"javascript\">\r\n");
sb.append(" function turnOverPage(no){\r\n");
sb.append(" var form = document.pageController;\r\n");
sb.append(" //页号越界处理\r\n");
sb.append(" if (no").append(">").append(totalPage).append("){\r\n");
sb.append(" no=").append(totalPage).append(";\r\n");
sb.append(" }\r\n");
sb.append(" if (no").append("<=0){\r\n");
sb.append(" no=1;\r\n");
sb.append(" }\r\n");
sb.append(" form.").append(PAGE_NO).append(".value=no;\r\n");
sb.append(" form.action=\"").append(gotoUrl).append("\";\r\n");
sb.append(" form.submit();\r\n");
sb.append(" }\r\n");
sb.append("</script>\r\n");
try {
pageContext.getOut().print(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
return super.doStartTag();
}
public String getGotoUrl() {
return gotoUrl;
}
public void setGotoUrl(String gotoUrl) {
this.gotoUrl = gotoUrl;
}
/**
* 根据总记录数得到总页数
*
* @return int 总页数
*/
private int getTotalPage(int total) {
int totalPage = 1;
if (total == 0) {
totalPage = 1;
} else {
totalPage = (total % DEFAULTPAGESIZE == 0) ? (total / DEFAULTPAGESIZE) : (total
/ DEFAULTPAGESIZE + 1);
}
return totalPage;
}
}
以上没加上 样式,有些丑陋
定义了分页标签,肯定得需要定义标签
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>pageControllerTag</short-name>
<uri>http://code.google.com/samung/tag1.0</uri>
<tag>
<name>paginator</name>
<tag-class>com.chinadim.cpa.core.dao.support.PageControllerTag</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>gotoUrl</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
核心的处理分页记录的类
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
public Page pagedQuery(String hql, int pageNo, int pageSize, Object... values) {
Assert.hasText(hql);
Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
int startIndex = Page.getStartOfPage(pageNo, pageSize);
return pagedQueryWithStartIndex(hql, startIndex, pageSize, values);
}
/**
* 分页查询函数,使用已设好查询条件与排序的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(Criteria criteria, int pageNo, int pageSize) {
Assert.notNull(criteria);
Assert.isTrue(pageNo >= 1, "pageNo should start from 1");
int startIndex = Page.getStartOfPage(pageNo, pageSize);
return pageQueryWithStartIndex(criteria, startIndex, pageSize);
}
/**
* 分页查询函数,使用hql.
*
* @param pageNo 页号,从1开始.
*/
public Page pagedQueryWithStartIndex(String hql, int startIndex, int pageSize, Object... values) {
Assert.hasText(hql);
Assert.isTrue(startIndex >= 0, "pageNo should start from 1");
// Count查询
String countQueryString = " select count (*) " + removeSelect(removeOrders(hql));
List countlist = getHibernateTemplate().find(countQueryString, values);
long totalCount = (Long) countlist.get(0);
if (totalCount < 1)
return new Page();
Query query = createQuery(hql, values);
List list = query.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* 分页查询函数,根据查询条件进行查询 使用startIndex作为参数进行查询
* @param criteria
* @param start
* @param pageSize
* @return
*/
public Page pageQueryWithStartIndex(Criteria criteria, int startIndex, int pageSize){
Assert.notNull(criteria);
Assert.isTrue(startIndex >= 0, "start index should start from 1");
CriteriaImpl impl = (CriteriaImpl) criteria;
// 先把Projection和OrderBy条件取出来,清空两者来执行Count操作
Projection projection = impl.getProjection();
List<CriteriaImpl.OrderEntry> orderEntries;
try {
orderEntries = (List) BeanUtils.forceGetProperty(impl, "orderEntries");
BeanUtils.forceSetProperty(impl, "orderEntries", new ArrayList());
} catch (Exception e) {
throw new InternalError(" Runtime Exception impossibility throw ");
}
// 执行查询
int totalCount = (Integer) criteria.setProjection(Projections.rowCount()).uniqueResult();
// 将之前的Projection和OrderBy条件重新设回去
criteria.setProjection(projection);
if (projection == null) {
criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
}
try {
BeanUtils.forceSetProperty(impl, "orderEntries", orderEntries);
} catch (Exception e) {
throw new InternalError(" Runtime Exception impossibility throw ");
}
// 返回分页对象
if (totalCount < 1)
return new Page();
List list = criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();
return new Page(startIndex, totalCount, pageSize, list);
}
/**
* 分页查询函数,根据entityClass和查询条件参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(Class entityClass, int pageNo, int pageSize, Criterion... criterions) {
Criteria criteria = createCriteria(entityClass, criterions);
return pagedQuery(criteria, pageNo, pageSize);
}
/**
* 分页查询函数,根据entityClass和查询条件参数,排序参数创建默认的<code>Criteria</code>.
*
* @param pageNo 页号,从1开始.
* @return 含总记录数和当前页数据的Page对象.
*/
public Page pagedQuery(Class entityClass, int pageNo, int pageSize, String orderBy, boolean isAsc,
Criterion... criterions) {
Criteria criteria = createCriteria(entityClass, orderBy, isAsc, criterions);
return pagedQuery(criteria, pageNo, pageSize);
}
Page类操作
public class Page implements Serializable {
private static final long serialVersionUID = 1L;
private static final int DEFAULT_PAGE_SIZE = Integer.parseInt(Constants.PAGE_DEFAULT_LIMIT);
private int pageSize = DEFAULT_PAGE_SIZE; // 每页的记录数
private long start; // 当前页第一条数据在List中的位置,从0开始
private Object data; // 当前页中存放的记录,类型一般为List
private long totalCount; // 总记录数
/**
* 构造方法,只构造空页.
*/
public Page() {
this(0, 0, DEFAULT_PAGE_SIZE, new ArrayList());
}
/**
* 默认构造方法.
*
* @param start 本页数据在数据库中的起始位置
* @param totalSize 数据库中总记录条数
* @param pageSize 本页容量
* @param data 本页包含的数据
*/
public Page(long start, long totalSize, int pageSize, Object data) {
this.pageSize = pageSize;
this.start = start;
this.totalCount = totalSize;
this.data = data;
}
/**
* 取总记录数.
*/
public long getTotalCount() {
return this.totalCount;
}
/**
* 取总页数.
*/
public long getTotalPageCount() {
if (totalCount % pageSize == 0)
return totalCount / pageSize;
else
return totalCount / pageSize + 1;
}
/**
* 取每页数据容量.
*/
public int getPageSize() {
return pageSize;
}
/**
* 取当前页中的记录.
*/
public Object getResult() {
return data;
}
/**
* 取该页当前页码,页码从1开始.
*/
public long getCurrentPageNo() {
return start / pageSize + 1;
}
/**
* 该页是否有下一页.
*/
public boolean hasNextPage() {
return this.getCurrentPageNo() < this.getTotalPageCount() - 1;
}
/**
* 该页是否有上一页.
*/
public boolean hasPreviousPage() {
return this.getCurrentPageNo() > 1;
}
/**
* 获取任一页第一条数据在数据集的位置,每页条数使用默认值.
*
* @see #getStartOfPage(int,int)
*/
protected static int getStartOfPage(int pageNo) {
return getStartOfPage(pageNo, DEFAULT_PAGE_SIZE);
}
/**
* 获取任一页第一条数据在数据集的位置.
*
* @param pageNo 从1开始的页号
* @param pageSize 每页记录条数
* @return 该页第一条数据
*/
public static int getStartOfPage(int pageNo, int pageSize) {
return (pageNo - 1) * pageSize;
}
}
具体的ACTION应用和页面加载
private String pageNo = "1";
private String total = "0";
public String getTotal() {
return total;
}
public void setTotal(String total) {
this.total = total;
}
public String getPageNo() {
return pageNo;
}
public void setPageNo(String pageNo) {
this.pageNo = pageNo;
}
@SuppressWarnings("unchecked")
public String showJspTagList() throws Exception {
Page page = cpaInfoTestManager.findPaginatorByAllConditions(
Integer.parseInt(pageNo), Integer.parseInt(Constants.PAGE_DEFAULT_LIMIT));
total = String.valueOf(page.getTotalCount());
cpaInfoTestList = (List<CpaInfoTest>)page.getResult();
return SUCCESS;
}
页面部分加载
<%@ taglib uri="http://code.google.com/samung/tag1.0" prefix="myTag" %>
<myTag:paginator gotoUrl="${pageContext.request.contextPath}/cpatest/showJspTagList.action"></myTag:paginator>
第一种方式即可实现分页
第二种方式是差不多的,只是没用到自定义的标签
@SuppressWarnings("unchecked")
public class Page {
public static final int DEFAULT_PAGE_SIZE = 20;
public static final int DEFAULT_PAGE = 1;
private String url;
private int currentPage = 1;
private int pageSize = DEFAULT_PAGE_SIZE;
private long totalCount = -1;
private long totalPage;
private List data;
public Page() {
super();
}
public Page(int currentPage) {
this.currentPage = currentPage;
}
public Page(int currentPage, int pageSize) {
this.currentPage = currentPage;
this.pageSize = pageSize;
}
public int getStart() {
return (getCurrentPage() - 1) * pageSize;
}
public int getCurrentPage() {
if (currentPage > getTotalPage()) {
return (int) getTotalPage();
} else if (currentPage < 1) {
return 1;
} else {
return currentPage;
}
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public List getData() {
return data;
}
public void setData(List data) {
this.data = data;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public long getTotalCount() {
return totalCount;
}
public void setTotalCount(long totalCount) {
this.totalCount = totalCount;
}
public long getTotalPage() {
if (totalCount % pageSize == 0) {
totalPage = totalCount / pageSize;
return totalPage;
} else {
totalPage = totalCount / pageSize + 1;
return totalPage;
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Page帮助类
public class PageHelper {
public static Page getPageFromRequest(HttpServletRequest request) {
return getPageFromRequest(request, 0);
}
public static Page getPageFromRequest(HttpServletRequest request,
int pageSize) {
Page page = new Page();
int currentPage = 1;
StringBuffer querySb = new StringBuffer();
Map paramMap = request.getParameterMap();
for (Iterator it = paramMap.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
if (key.equals("page")) {
String[] values = (String[]) paramMap.get(key);
String str = values[0];
if (str.equals(""))
continue;
try {
currentPage = Integer.parseInt(str);
} catch (Exception e) {
currentPage = Page.DEFAULT_PAGE;
}
continue;
}
String[] values = (String[]) paramMap.get(key);
if (key.equals("pageSize")) {
String str = values[0];
try {
pageSize = Integer.parseInt(str);
} catch (Exception e) {
}
}
for (int i = 0; i < values.length; i++) {
try {
querySb.append("&" + key + "="
+ URLEncoder.encode(values[i], "GBK"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
if (querySb.length() != 0) {
querySb.setCharAt(0, '?');
querySb.append('&');
} else {
querySb.append('?');
}
page.setCurrentPage(currentPage);
if (pageSize != 0)
page.setPageSize(pageSize);
page.setUrl(request.getRequestURL().append(querySb).toString());
return page;
}
}
PaginationUtils类
public class PaginationUtils {
private static DateFormat FMT = new SimpleDateFormat("yyyy-MM-dd hh:mm");
public static String notNull(Object value, String out) {
return value == null ? out : value.toString();
}
public static String notNull(Object value) {
return notNull(value, "");
}
public static String notZero(int value, String out) {
return value == 0 ? out : String.valueOf(value);
}
public static String notZero(int value) {
return notZero(value, "");
}
public static String formatDate(Calendar date) {
return FMT.format(date.getTime());
}
public static String createPageNavigator(Page page) {
// 第?页 共?页上一页下一页 跳转到?
StringBuffer sb = new StringBuffer();
sb.append("<span>").append("第 ").append(page.getCurrentPage())
.append(" 页 ").append("共 ").append(
page.getTotalPage()).append(" 页 ").append(
"共 ").append(page.getTotalCount()).append(
" 条 ");
if (page.getCurrentPage() > 1) {
sb.append("<a href=\"").append(page.getUrl()).append("page=")
.append(1).append("\">首页</a> ");
sb.append("<a href=\"").append(page.getUrl()).append("page=")
.append(page.getCurrentPage() - 1).append(
"\">上一页</a> ");
}
if (page.getCurrentPage() < page.getTotalPage()) {
sb.append("<a href=\"").append(page.getUrl()).append("page=")
.append(page.getCurrentPage() + 1).append(
"\">下一页</a> ");
sb.append("<a href=\"").append(page.getUrl()).append("page=")
.append(page.getTotalPage()).append("\">末页</a> ");
}
sb.append("</span>");
return sb.toString();
}
public static void main(String[] args) {
}
}
具体应用上的
private Page pageList;
@SuppressWarnings("unchecked")
public String cpaAccountList() throws Exception {
//填充到map对象,用于页面取
cpaUserKeyMap.clear();
cpaUserKeyMap.putAll(fillCpaUserKey());
pageList = PageHelper.getPageFromRequest(getRequest());
pageList = cpaAccountManager.fetchAllCpaAccountList(cpaAccount, pageList);
return SUCCESS;
}
jsp页面直接用struts2的标签输出即可
<ww:text name="%{@com.chinadim.cpa.utils.PaginationUtils@createPageNavigator(pageList)}"/>