java 分页

来源:互联网 发布:波斯人信札知乎 编辑:程序博客网 时间:2024/05/16 12:57

分页,这项功能在每个页面可能都会体现到,如果每个页面都有,那好我们就把分页这部分抽象,看下面代码

页面:

  1. <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
  2. <%@ taglib prefix="s" uri="/struts-tags" %>  
  3.   
  4. <div id=PageSelectorBar>  
  5.     <div id=PageSelectorMemo>  
  6.         页次:${currentPage}/${pageCount }页    
  7.         每页显示:${pageSize }条    
  8.         总记录数:${recordCount }条  
  9.     </div>  
  10.     <div id=PageSelectorSelectorArea>  
  11.       
  12.         <a href="javascript: gotoPage(1)" title="首页" style="cursor: hand;">  
  13.             <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png"/>  
  14.         </a>  
  15.           
  16.         <s:iterator begin="%{beginPageIndex}" end="%{endPageIndex}" var="num">  
  17.             <s:if test="#num == currentPage"> <%-- 当前页 --%>  
  18.                 <span class="PageSelectorNum PageSelectorSelected">${num}</span>  
  19.             </s:if>  
  20.             <s:else> <%-- 非当前页 --%>  
  21.                 <span class="PageSelectorNum" style="cursor: hand;" onClick="gotoPage(${num});">${num}</span>  
  22.             </s:else>  
  23.               
  24.         </s:iterator>  
  25.           
  26.         <a href="javascript: gotoPage(${pageCount})" title="尾页" style="cursor: hand;">  
  27.             <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png"/>  
  28.         </a>  
  29.           
  30.         转到:  
  31.         <select onchange="gotoPage(this.value)" id="_pn">  
  32.             <s:iterator begin="1" end="%{pageCount}" var="num">  
  33.                 <option value="${num}">${num}</option>  
  34.             </s:iterator>  
  35.         </select>  
  36.         <script type="text/javascript">  
  37.             $("#_pn").val("${currentPage}");  
  38.         </script>  
  39.           
  40.     </div>  
  41. </div>  
  42.   
  43.   
  44. <script type="text/javascript">  
  45.     function gotoPage( pageNum ){  
  46.         // window.location.href = "forum_show.action?id=${id}&pageNum=" + pageNum;  
  47.           
  48.         $(document.forms[0]).append("<input type='hidden' name='pageNum' value='" + pageNum +"'>");  
  49.         document.forms[0].submit();  
  50.     }  
  51. </script>  

这样我们在有分页的页面中只需写这样的一段代码就搞定了。

  1. <!--分页信息-->  
  2. <%@ include file="/WEB-INF/jsp/public/pageView.jspf" %>  

PageBean代码:

  1. package cn.itcast.oa.domain;  
  2.   
  3. import java.util.List;  
  4.   
  5. /** 
  6.  * 分页功能中的一页的信息 
  7.  *  
  8.  * @author 志鹏 
  9.  *  
  10.  */  
  11. public class PageBean {  
  12.   
  13.     // 指定的或是页面参数  
  14.     private int currentPage; // 当前页  
  15.     private int pageSize; // 每页显示多少条  
  16.   
  17.     // 查询数据库  
  18.     private int recordCount; // 总记录数  
  19.     private List recordList; // 本页的数据列表  
  20.   
  21.     // 计算  
  22.     private int pageCount; // 总页数  
  23.     private int beginPageIndex; // 页码列表的开始索引(包含)  
  24.     private int endPageIndex; // 页码列表的结束索引(包含)  
  25.   
  26.     /** 
  27.      * 只接受前4个必要的属性,会自动的计算出其他3个属生的值 
  28.      *  
  29.      * @param currentPage 
  30.      * @param pageSize 
  31.      * @param recordCount 
  32.      * @param recordList 
  33.      */  
  34.     public PageBean(int currentPage, int pageSize, int recordCount, List recordList) {  
  35.         this.currentPage = currentPage;  
  36.         this.pageSize = pageSize;  
  37.         this.recordCount = recordCount;  
  38.         this.recordList = recordList;  
  39.   
  40.         // 计算总页码  
  41.         pageCount = (recordCount + pageSize - 1) / pageSize;  
  42.   
  43.         // 计算 beginPageIndex 和 endPageIndex  
  44.         // >> 总页数不多于10页,则全部显示  
  45.         if (pageCount <= 10) {  
  46.             beginPageIndex = 1;  
  47.             endPageIndex = pageCount;  
  48.         }  
  49.         // >> 总页数多于10页,则显示当前页附近的共10个页码  
  50.         else {  
  51.             // 当前页附近的共10个页码(前4个 + 当前页 + 后5个)  
  52.             beginPageIndex = currentPage - 4;  
  53.             endPageIndex = currentPage + 5;  
  54.             // 当前面的页码不足4个时,则显示前10个页码  
  55.             if (beginPageIndex < 1) {  
  56.                 beginPageIndex = 1;  
  57.                 endPageIndex = 10;  
  58.             }  
  59.             // 当后面的页码不足5个时,则显示后10个页码  
  60.             if (endPageIndex > pageCount) {  
  61.                 endPageIndex = pageCount;  
  62.                 beginPageIndex = pageCount - 10 + 1;  
  63.             }  
  64.         }  
  65.     }  
  66. }  

上面代码中的一些get set(记得写)方法我删除了,看到上面这个类中的方法和业务逻辑其实并不难,但是如果重复性的工作多了,这些东西也是够折磨你的

QueryHelper工具类:

  1. <span style="font-size:18px;">package cn.itcast.oa.util;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import cn.itcast.oa.base.DaoSupport;  
  7. import cn.itcast.oa.domain.PageBean;  
  8.   
  9. import com.opensymphony.xwork2.ActionContext;  
  10.   
  11. /** 
  12.  * 用于辅助拼接HQL语句 
  13.  *  
  14.  * @author 志鹏 
  15.  *  
  16.  */  
  17. public class QueryHelper {  
  18.   
  19.     private String fromClause; // FROM子句  
  20.     private String whereClause = ""// Where子句  
  21.     private String orderByClause = ""// OrderBy子句  
  22.   
  23.     private List<Object> parameters = new ArrayList<Object>(); // 参数列表  
  24.   
  25.     /** 
  26.      * 生成From子句 
  27.      *  
  28.      * @param clazz 
  29.      * @param alias 
  30.      *            别名 
  31.      */  
  32.     public QueryHelper(Class clazz, String alias) {  
  33.         fromClause = "FROM " + clazz.getSimpleName() + " " + alias;  
  34.     }  
  35.   
  36.     /** 
  37.      * 拼接Where子句 
  38.      *  
  39.      * @param condition 
  40.      * @param params 
  41.      */  
  42.     public QueryHelper addCondition(String condition, Object... params) {  
  43.         // 拼接  
  44.         if (whereClause.length() == 0) {  
  45.             whereClause = " WHERE " + condition;  
  46.         } else {  
  47.             whereClause += " AND " + condition;  
  48.         }  
  49.   
  50.         // 参数  
  51.         if (params != null) {  
  52.             for (Object p : params) {  
  53.                 parameters.add(p);  
  54.             }  
  55.         }  
  56.   
  57.         return this;  
  58.     }  
  59.   
  60.     /** 
  61.      * 如果第一个参数为true,则拼接Where子句 
  62.      *  
  63.      * @param append 
  64.      * @param condition 
  65.      * @param params 
  66.      */  
  67.     public QueryHelper addCondition(boolean append, String condition, Object... params) {  
  68.         if (append) {  
  69.             addCondition(condition, params);  
  70.         }  
  71.         return this;  
  72.     }  
  73.   
  74.     /** 
  75.      * 拼接OrderBy子句 
  76.      *  
  77.      * @param propertyName 
  78.      *            参与排序的属性名 
  79.      * @param asc 
  80.      *            true表示升序,false表示降序 
  81.      */  
  82.     public QueryHelper addOrderProperty(String propertyName, boolean asc) {  
  83.         if (orderByClause.length() == 0) {  
  84.             orderByClause = " ORDER BY " + propertyName + (asc ? " ASC" : " DESC");  
  85.         } else {  
  86.             orderByClause += ", " + propertyName + (asc ? " ASC" : " DESC");  
  87.         }  
  88.         return this;  
  89.     }  
  90.   
  91.     /** 
  92.      * 如果第一个参数为true,则拼接OrderBy子句 
  93.      *  
  94.      * @param append 
  95.      * @param propertyName 
  96.      * @param asc 
  97.      */  
  98.     public QueryHelper addOrderProperty(boolean append, String propertyName, boolean asc) {  
  99.         if (append) {  
  100.             addOrderProperty(propertyName, asc);  
  101.         }  
  102.         return this;  
  103.     }  
  104.   
  105.     /** 
  106.      * 获取生成的用于查询数据列表的HQL语句 
  107.      *  
  108.      * @return 
  109.      */  
  110.     public String getListQueryHql() {  
  111.         return fromClause + whereClause + orderByClause;  
  112.     }  
  113.   
  114.     /** 
  115.      * 获取生成的用于查询总记录数的HQL语句 
  116.      *  
  117.      * @return 
  118.      */  
  119.     public String getCountQueryHql() {  
  120.         return "SELECT COUNT(*) " + fromClause + whereClause;  
  121.     }  
  122.   
  123.     /** 
  124.      * 获取HQL中的参数值列表 
  125.      *  
  126.      * @return 
  127.      */  
  128.     public List<Object> getParameters() {  
  129.         return parameters;  
  130.     }  
  131.   
  132.     /** 
  133.      * 查询分页信息,并放到值栈栈顶 
  134.      *  
  135.      * @param service 
  136.      * @param pageNum 
  137.      * @param pageSize 
  138.      */  
  139.     public void preparePageBean(DaoSupport<?> service, int pageNum, int pageSize) {  
  140.         PageBean pageBean = service.getPageBean(pageNum, pageSize, this);  
  141.         ActionContext.getContext().getValueStack().push(pageBean);  
  142.     }  
  143.   
  144. }  
  145. </span>  

简单介绍,如果我们的参数过多,我们可以根据循环来进行赋值,这样都避免了赋值繁杂,和一些空格的错误了。

OA系统的抽象不仅仅这些,比如一些公共的GetById(),FindAll()等等这样公共的底层方法,我们都抽象到了一个叫做DaoSupportImpl这样的实现类中,那么我们的分页功能也有这样的公共方法我们依旧抽象出来放在DaoSupportImpl实现类中,看下面代码:

PageBean方法:

  1. <span style="font-size:18px;">// 公共的查询分页信息的方法(最终版)  
  2.         public PageBean getPageBean(int pageNum, int pageSize, QueryHelper queryHelper) {  
  3.               
  4.             // 参数列表  
  5.             List<Object> parameters = queryHelper.getParameters();  
  6.   
  7.             // 查询本页的数据列表  
  8.             Query listQuery = getSession().createQuery(queryHelper.getListQueryHql()); // 创建查询对象  
  9.             if (parameters != null) { // 设置参数  
  10.                 for (int i = 0; i < parameters.size(); i++) {  
  11.                     listQuery.setParameter(i, parameters.get(i));  
  12.                 }  
  13.             }  
  14.             listQuery.setFirstResult((pageNum - 1) * pageSize);  
  15.             listQuery.setMaxResults(pageSize);  
  16.             List list = listQuery.list(); // 执行查询  
  17.   
  18.             // 查询总记录数量  
  19.             Query countQuery = getSession().createQuery(queryHelper.getCountQueryHql());  
  20.             if (parameters != null) { // 设置参数  
  21.                 for (int i = 0; i < parameters.size(); i++) {  
  22.                     countQuery.setParameter(i, parameters.get(i));  
  23.                 }  
  24.             }  
  25.             Long count = (Long) countQuery.uniqueResult(); // 执行查询  
  26.   
  27.             return new PageBean(pageNum, pageSize, count.intValue(), list);  
  28.         }  
  29.       
  30.     </span>  
注一
大家也许会奇怪,那怎么进行具体的查询呢,比如我是板块查询,没有看到真正的hql语句和表的查询呀,当然我们一些特殊的我们会进行重写呀,比如下面这段代码,就是重写的过程:

  1. <span style="font-size:18px;">public PageBean getPageBeanByForum(int pageNum, int pageSize, Forum forum) {  
  2.   
  3.         // 查询本页的数据列表  
  4.         List list = getSession().createQuery(//  
  5.                 "FROM Topic t WHERE t.forum=? ORDER BY (CASE t.type WHEN 2 THEN 2 ELSE 0 END) DESC, t.lastUpdateTime DESC")//  
  6.                 .setParameter(0, forum)//  
  7.                 .setFirstResult((pageNum - 1) * pageSize)//  
  8.                 .setMaxResults(pageSize)//  
  9.                 .list();  
  10.   
  11.         // 查询总记录数量  
  12.         Long count = (Long) getSession().createQuery(//  
  13.                 "SELECT COUNT(*) FROM Topic t WHERE t.forum=?")//  
  14.                 .setParameter(0, forum)//  
  15.                 .uniqueResult();  
  16.   
  17.         return new PageBean(pageNum, pageSize, count.intValue(), list);  
  18.     }</span>  
注二:

关于这段内容都这些了,让我很疑惑的是,在action中的hql语句,是不是会让我们的架构设计不够明确呢,hql语句应该放在底层,而不是Action呀,看下面代码:

Action代码:

  1. <span style="font-size:18px;">// 准备分页信息 ,最终版  
  2.         new QueryHelper(Topic.class"t")//  
  3.                 // 过滤条件  
  4.                 .addCondition("t.forum=?", forum)//  
  5.                 .addCondition((viewType == 1), "t.type=?", Topic.TYPE_BEST) // 1 表示只看精华帖  
  6.                 // 排序条件  
  7.                 .addOrderProperty((orderBy == 1), "t.lastUpdateTime", asc) // 1 表示只按最后更新时间排序  
  8.                 .addOrderProperty((orderBy == 2), "t.postTime", asc) // 2 表示只按主题发表时间排序  
  9.                 .addOrderProperty((orderBy == 3), "t.replyCount", asc) // 3 表示只按回复数量排序  
  10.                 .addOrderProperty((orderBy == 0), "(CASE t.type WHEN 2 THEN 2 ELSE 0 END)"false)//  
  11.                 .addOrderProperty((orderBy == 0), "t.lastUpdateTime"false// 0 表示默认排序(所有置顶帖在前面,并按最后更新时间降序排列)  
  12.                 .preparePageBean(topicService, pageNum, pageSize);  
  13. </span>  
 注一和注二可以替换为:

public String list() throws Exception {
PageBean pageBean = new QueryHelper(User.class, "u")//
.preparePageBean(userService, pageNum, pageSize);
//结果放到栈顶
ActionContext.getContext().getValueStack().push(pageBean);
return "list";
}

在jsp中的应用:

<s:form action="userAction_list"></s:form>//查下一页时,先从后台查询数据
<%@ include file="/WEB-INF/jsp/public/pageView.jspf" %>//此页面便是存放数据分页的jsp页面,即最上面页面代码

0 0
原创粉丝点击