标签:
本文来源于 http://blog.csdn.net/tjpu_lin/article/details/41050475
近期在开发一个项目,项目中有非常多数据展示的模块。所以要用到分页,网上搜了非常多分页的样例,可是非常多实现的方法和自身的代码实例耦合度太高。导致直接拿来用根本不行。
于是自己仅仅能亲自上阵了,关于分页实现大体逻辑是前台须要和后台相互传递页面參数(比如当前页面,页面大小。总共页数等),后台主要接受前台穿过来的pageNum(当前页码),进行数据查询,然后查完数据后返回给前台的同一时候也要将页面返回给前台。好让前台结合CSS在分页样式中高亮显示出当前页。
步骤大体能够分为下面几步。
1.后台sql查询数据时(底层我用的是Mysql数据库)
前台仅仅须要传递一个pageNum,然后后台定义个页面大小的常量吧,我是定义到Constant类里面。作为一个常量来使用的。
/** * 分页页面參数 */ public static final Integer PAGESIZE = 10;
这时候我们须要了解mysql分页的sql的实现是这种:
在mysql中,我们用limit来实现分页数据的查询,limit A,B 表示从A開始,往后取B个数。
对于我们来说,第一页就是0-9这10条记录(mysql记录的索引是从0開始的)。所以我们第一页取的数据相应的sql是 limit 0,10。以此类推第二页是 limit 10,10,第三页是 limit 20,10 ......
開始的索引值须要我们进行一个简单的计算。Integer startIndex = (pageNum-1)*10,,不理解的将pageNum值代入想一想就知道了。
limit startIndex 。PAGESIZE始终都是放在查询的最后面。即前面什么各种where 。group by, order by所有写好后再接limit
2.后台pageVo类的构建
由于前台须要后台的数据比較多,所以我们将它们封装到一个pageVo对象里面。
以下是我pageVo类的定义
package com.bada.core.vo; import java.io.Serializable; import java.util.Map; /** * @author Kevin * 用于分页的类 */ public class PageVo implements Serializable { private int curPage;//当前页 private int pageSize;//每页的大小 private int totalRows;//总记录数 private int totalPages;//总页数 private String queryCondition; //查询条件(字符串),用户将查询条件穿到前台然后再传回来 private Map<String,Object> queryConditions; //查询条件,针对多条件 public Map<String, Object> getQueryConditions() { return queryConditions; } public void setQueryConditions(Map<String, Object> queryConditions) { this.queryConditions = queryConditions; } public int getCurPage() { return curPage; } public void setCurPage(int curPage) { this.curPage = curPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotalRows() { return totalRows; } public void setTotalRows(int totalRows) { this.totalRows = totalRows; } public int getTotalPages() { return totalPages; } public void setTotalPages(int totalPages) { this.totalPages = totalPages; } public String getQueryCondition() { return queryCondition; } public void setQueryCondition(String queryCondition) { this.queryCondition = queryCondition; } @Override public String toString() { return "PageVo{" + "curPage=" + curPage + ", pageSize=" + pageSize + ", totalRows=" + totalRows + ", totalPages=" + totalPages + ", queryCondition='" + queryCondition + '\'' + ", queryConditions=" + queryConditions + '}'; } }
后台须要new一个PageVo的对象出来。然后set相应的參数值,curPage就是pageNum,pageSize是页面大小。这里要注意的事。在进行数据查询后,还须要对满足条件的全部记录做一个计数,去获取总数值。一般 select count(ID) from ** where **=**, 一般不要count(*),查询效率会低非常多的,count(0)就能够了。当然count(主键)会更快,由于主键是加了索引的。
totalRows相应刚才查询出来的总数。totalPages也是须要我们去计数的。思考一下。一共须要的页面数。我们先弄几个样例来推敲一下,假设有40条记录,依据1页是10条记录,那么就是4页。假设有38条记录,也是4页。事实上就是一个总数除以页面大小向上取整。我们写一个方法去实现。
public class FormatUtils { /** * 向上取整 比如: 30条数据。每页8条 一共4页 * @param total * @param pageSize * @return */ public static int getPageTotal(int total,int pageSize){ if(pageSize == 0){//分母不能为0 return 0; } return (int)Math.ceil((double)total/pageSize); } }java自带了Math.ceil用来取大于或等于某个数的最小整数。
假设有一个查询条件就set到queryCondition中去,假设有多个就封装到map再set到queryCondtions里面去、详细前台怎么取在后面诉述、
3.前台jstl构建页面元素。
開始是写在页面上一大串jstl代码来生成html代码,后来直接封装到自己定义标签中要方便的多。先展示一下jstl是怎样写的。
<div class="page mg-auto"> <ul class="pagination"> <c:if test="${pageVo.totalPages > 0}"> <li><a href="javascript:onSelectPage(${pageVo.curPage - 1})">«</a></li> <c:if test="${pageVo.totalPages <= 10}"> <c:forEach var="i" begin="1" end="${pageVo.totalPages}"> <c:choose> <c:when test="${i == pageVo.curPage}"> <li class="active"><a href="javascript:onSelectPage(${i})">${i}</a></li> </c:when> <c:otherwise> <li><a href="javascript:onSelectPage(${i})">${i}</a></li> </c:otherwise> </c:choose> </c:forEach> </c:if> <c:if test="${pageVo.totalPages > 10}"> <c:if test="${pageVo.curPage < 10}"> <c:forEach var="i" begin="1" end="10"> <c:choose> <c:when test="${i == pageVo.curPage}"> <li class="active"><a href="javascript:onSelectPage(${i})">${i}</a></li> </c:when> <c:otherwise> <li><a href="javascript:onSelectPage(${i})">${i}</a></li> </c:otherwise> </c:choose> </c:forEach> </c:if> <c:if test="${pageVo.curPage >= 10}"> <c:forEach var="j" begin="${pageVo.curPage-5}" end="${pageVo.curPage+4}"> <c:if test="${j <= pageVo.totalPages}"> <c:choose> <c:when test="${j == pageVo.curPage}"> <li class="active"><a href="javascript:onSelectPage(${j})">${j}</a></li> </c:when> <c:otherwise> <li><a href="javascript:onSelectPage(${j})">${j}</a></li> </c:otherwise> </c:choose> </c:if> </c:forEach> </c:if> </c:if> <li><a href="javascript:onSelectPage(${pageVo.curPage + 1})">»</a></li> </c:if> </ul> </div>
后来才发现上面的代码事实上能够用自己定义标签实现,页面上一行代码就搞定。重用性高多了~ 后面讲这个!
。
详细的实现逻辑是模仿百度分页的走的,
须要分析的逻辑例如以下(步步递进):
1、一条记录都没有,不显示页码。 推断pageVo的totalPages是否大于0。假设大于0,才去生成分页样式
2、假设总页数小于10,则写一个循环,从1開始。循环到总页数,显示N页(N为totalPages),显示这N页的同一时候,依据pageVo里面的curPage推断哪一页须要高亮显示出来。
3、假设总页数大于10,小于10的部分显示效果如上。大于10的时候,高亮页面始终在中间区域,即以当前页curPage做为条件。它的左边显示5个,右边显示4个。(详细效果能够看看百度搜索完结果的最下方)
一次性最多展示10页。然后高亮显示在中间(页面大于10)。
每个a标签都要加js函数。当点击的时候跳到以下的函数里面。
<c:if test="${!empty pageVo}"> <%--防止首次进入该页面时没有pageVo而出js错误--%> <script type="text/javascript"> function onSelectPage(curPage){ if(curPage>=1 && curPage<=${pageVo.totalPages}){ if (curPage != ${pageVo.curPage}) { //当前页点击禁用跳转 window.location.href="${pageContext.request.contextPath}/customer/queryAllSalesShippers?pageNum="+curPage; } } } </script> </c:if>假设带查询条件的这么去写
window.location.href="${pageContext.request.contextPath}/customer/querySalesShipperCustomer?condition=${pageVo.queryCondition}&pageNum="+curPage;
详细样子
/*------------------------------分页 tag defines-------------------------------*/ .page{width:80%;text-align:center;margin-top:80px;} .pagination { display: inline-block; padding-left: 0; margin: 20px 0; border-radius: 2px;} .pagination>li { display: inline; } :before, :after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } :before, :after { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .pagination>li:first-child>a, .pagination>li:first-child>span { margin-left: 0; border-top-left-radius: 2px; border-bottom-left-radius: 2px; } .pagination>li>a, .pagination>li>span { position: relative; float: left; padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; color: #428bca; text-decoration: none; background-color: #fff; border: 1px solid #ddd; } a { text-decoration: none; } a { background: 0 0; } .pagination>.active>a, .pagination>.active>span, .pagination>.active>a:hover, .pagination>.active>span:hover, .pagination>.active>a:focus, .pagination>.active>span:focus { color: #fff; cursor: default; background-color: #428bca; border-color: #428bca; } .pagination>li>a:hover, .pagination>li>span:hover, .pagination>li>a:focus, .pagination>li>span:focus { color: #2a6496; background-color: #eee; border-color: #ddd; } .pagination>.active>a, .pagination>.active>span, .pagination>.active>a:hover, .pagination>.active>span:hover, .pagination>.active>a:focus, .pagination>.active>span:focus { color: #fff; cursor: default; background-color: #428bca; border-color: #428bca; } .pagination>li>a, .pagination>li>span { position: relative; float: left; padding: 6px 12px; margin-left: -1px; line-height: 1.42857143; color: #428bca; text-decoration: none; background-color: #fff; border: 1px solid #ddd; }
以下说一下关于自己定义标签的实现
详细的思路就是用java代码去将html代码打印出来。就跟servlet用输出流打印页面一样。
1.构建自己定义标签类
package com.bada.biz.service; import javax.servlet.jsp.JspException; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.tagext.TagSupport; import com.bada.core.vo.PageVo; /** * Created by Kevin on 2014/11/2. * pageVo的自己定义标签类 */ public class PageVoTag extends TagSupport { private PageVo pageVo; @Override public int doStartTag() throws JspException { try { JspWriter out = this.pageContext.getOut(); if(pageVo == null) { return SKIP_BODY; } if (pageVo.getTotalPages() > 0) { out.println("<li><a href=\"javascript:onSelectPage("+(pageVo.getCurPage()-1)+")\">«</a></li>"); if (pageVo.getTotalPages() <= 10) { for (int i = 1; i <= pageVo.getTotalPages(); i++) { if (i == pageVo.getCurPage()) { out.println("<li class=\"active\"><a href=\"javascript:onSelectPage("+i+")\">"+i+"</a></li>"); } else { out.println("<li><a href=\"javascript:onSelectPage("+i+")\">"+i+"</a></li>"); } } } if (pageVo.getTotalPages() > 10) { if (pageVo.getCurPage() < 10) { for (int i = 1; i <= 10; i++) { if (i == pageVo.getCurPage()) { out.println("<li class=\"current\"><a href=\"javascript:onSelectPage("+i+")\">"+i+"</a></li>"); } else { out.println("<li><a href=\"javascript:onSelectPage("+i+")\">"+i+"</a></li>"); } } } if (pageVo.getCurPage() >= 10) { for (int j = pageVo.getCurPage()-5;j <= pageVo.getCurPage()+4; j++) { if (j <= pageVo.getTotalPages()) { if (j == pageVo.getCurPage()){ out.println("<li class=\"current\"><a href=\"javascript:onSelectPage("+j+")\">"+j+"</a></li>"); } else { out.println("<li><a href=\"javascript:onSelectPage("+j+")\">"+j+"</a></li>"); } } } } } out.println("<li><a href=\"javascript:onSelectPage("+(pageVo.getCurPage()+1)+")\">»</a></li>"); } } catch(Exception e) { throw new JspException(e.getMessage()); } return SKIP_BODY; } @Override public int doEndTag() throws JspException { return EVAL_PAGE; } @Override public void release() { super.release(); this.pageVo = null; } public PageVo getPageVo() { return pageVo; } public void setPageVo(PageVo pageVo) { this.pageVo = pageVo; } }
能够看到。代码明显比jstl少非常多。看来还是ava代码好使哇。这个类可能须要下载相应的jar包,这个自己百度一下。
<?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>cc</short-name> <uri>/pageTaglib</uri> <tag> <name>showPaging</name> <tag-class>com.bada.biz.service.PageVoTag</tag-class> <body-content>empty</body-content> <attribute> <name>pageVo</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> </taglib>
里面相应的tag-class就是上面写的那个类,pageVo为传入的參数,到时候前台用${pageVo}赋值这个參数。
3.web.xml里面的配置
<!--配置自己定义标签--> <jsp-config> <taglib> <taglib-uri>/pageTaglib</taglib-uri> <taglib-location>/WEB-INF/tld/pageVo.tld</taglib-location> </taglib> </jsp-config>
4.jsp页面使用
引用标签:uri是上面定义的uri。prefix为前缀名。随意取的
<%@ taglib uri="/pageTaglib" prefix="pv"%>
<div class="page mg-auto"> <ul class="pagination"> <pv:showPaging pageVo="${pageVo}" /> </ul> </div>
一行代码搞定。。再也不用不停copy 那一大串jstl代码了。
至此 分页模块搞定了,相关文件下载http://download.csdn.net/detail/tro_picana/8151805
版权声明:本文博主原创文章。博客,未经同意不得转载。
标签:
原文地址:http://www.cnblogs.com/hrhguanli/p/4853567.html