住javaWeb分页实现(模拟百度首页)

时间:2023-10-29 11:24:20

本文来源于 http://blog.csdn.net/tjpu_lin/article/details/41050475

近期在开发一个项目,项目中有非常多数据展示的模块。所以要用到分页,网上搜了非常多分页的样例,可是非常多实现的方法和自身的代码实例耦合度太高。导致直接拿来用根本不行。

于是自己仅仅能亲自上阵了,关于分页实现大体逻辑是前台须要和后台相互传递页面參数(比如当前页面,页面大小。总共页数等),后台主要接受前台穿过来的pageNum(当前页码),进行数据查询,然后查完数据后返回给前台的同一时候也要将页面返回给前台。好让前台结合CSS在分页样式中高亮显示出当前页。

步骤大体能够分为下面几步。

1.后台sql查询数据时(底层我用的是Mysql数据库)

前台仅仅须要传递一个pageNum,然后后台定义个页面大小的常量吧,我是定义到Constant类里面。作为一个常量来使用的。

  /**
* 分页页面參数
*/
public static final Integer PAGESIZE = 10;

使用的时候用Constant.PAGESIZE来调用。

这时候我们须要了解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 +
'}';
}
}

当中加的queryCondition和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;

当然window.location.href=""后面的连接写你查询数据的那个action路径。

关于相应的前端样式是前端去写的,仅仅要有带高亮样式的分页的html代码即可,这里我也贴出css代码好了。

详细样子

住javaWeb分页实现(模拟百度首页)

/*------------------------------分页 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;
}

我写的分页,简单步骤就是3步。后台pageVo构建,前台jstl生成分页模块。然后加个js函数去进行跳转查询



=========================================================我是切割线========================================================

以下说一下关于自己定义标签的实现

详细的思路就是用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包,这个自己百度一下。

2.自己定义标签文件    命名为  pageVo.tld

<?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>

加在web-app标签里面一级即可了

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

版权声明:本文博主原创文章。博客,未经同意不得转载。