住javaWeb分页实现(模拟百度首页)
本文来源于 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代码好了。
详细样子
/*------------------------------分页 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
版权声明:本文博主原创文章。博客,未经同意不得转载。
住javaWeb分页实现(模拟百度首页)的更多相关文章
- 使用Mybatis插件 PageHelper 模拟百度分页(Day_20)
生活中,要学会沉淀生命,沉淀心情,沉淀自己 模拟百度分页最终实现效果如图: 本篇博客运行环境 JDK8 + IntelliJ IDEA 2018.3 + Tomcat 8.5.31 准备好了我们就开始 ...
- 【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程
[前提] 想要实现使用某种语言,比如Python,C#等,去实现模拟登陆网站的话,首先要做的事情就是使用某种工具,去分析本身使用浏览器去登陆网页的时候,其内部的执行过程,内部逻辑. 此登陆的逻辑过程, ...
- Splinter学习--初探1,模拟百度搜索
Splinter是以Selenium, PhantomJS 和 zope.testbrowser为基础构建的web自动化测试工具,基本原理同selenium 支持的浏览器包括:Chrome, Fire ...
- Webbrowser模拟百度一下子点击事件
Webbrowser模拟百度一下点击事件新建一个form,有一个button和一个webbrowser控件.然后webbrowser一开始加载的就是百度主页.然后在文本框里输入点东西,如何做到点击bu ...
- C#模拟百度登录并到指定网站评论回帖(一)
核心信息: 请求网址: https://passport.baidu.com/v2/api/?login请求方法: POST状态码: HTTP/1.1 200 OK请求头 //用户代理 Use ...
- html布局小练习(百度首页)
绝对定位百度首页练习 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...
- POST模拟百度登录和自动发帖
这里用HttpClient发包模拟百度登录和发帖,验证码部分采用机器下载人工识别. 登陆百度的原理:1. 访问https://passport.baidu.com/v2/api/?getapi& ...
- Selenium2学习-009-WebUI自动化实战实例-007-Selenium 8种元素定位实战实例源代码(百度首页搜索录入框及登录链接)
此 文主要讲述用 Java 编写 Selenium 自动化测试脚本编写过程中,通过 ID.name.xpath.cssSelector.linkText.className.partialLinkTe ...
- jquery ajax json简单的分页,模拟数据,没有封装,只显示原理
简单的分页,模拟数据,没有封装,显示原理,大家有兴趣可以自己封装,这里只是个原理过程,真正的分页也差不多是这个原理,只是请求数据不太一样,html部分: <!TOCTYPE HTML> & ...
随机推荐
- C# winform xml的增删改查
代码如下: using System; using System.Collections.Generic; using System.IO; using System.Linq; using Syst ...
- 基本SQL语句练习之SELECT
一.SQL Plus连接sqlplus:以命令行方式连接数据库sqlplusw:以窗口登录方式连接数据库conn sys/password as sysdba;show userselect * fr ...
- openwrt sdk compile
recently ,bought a router : tl-wr741n-v5 hd my aim : let the router dail in neetkeeper environment : ...
- JAVA正则表达式之贪婪、勉强和侵占
在JAVA正则表达式中量词(quantifiers)允许指定匹配出现的次数,方便起见,当前 Pattern API 规范下,描述了贪婪.勉强和侵占三种量词.首先粗略地看一下,量词X?.X??和X?+都 ...
- Java 测试Hibernate+Mysql简单的数据存储
想使用Hibernate框架,在网上看了一个Hibernate学习视频,试着做了一个小小的Java连接数据库的操作,Java初学者一个,大家多多包涵 开发环境: 1.安装MySql, 2.安装了Ecl ...
- RAC 常用维护工具和命令(oracle 10g)
Oracle 的管理可以通过OEM或者命令行接口. Oracle Clusterware的命令集可以分为以下4种: 节点层:osnodes 网络层:oifcfg 集群层:crsctl, ocrchec ...
- web离线应用
其实浏览器一直都是前端开发人员比较头痛的一个课题,各种兼容性.直到开始规范化和标准化,HTML5的出现. 在没有这套标准出现之前,对于客户端缓存的问题,我们基本上都是用cookie处理,当然目前除了后 ...
- poj3252 组合数学
题目大意:给两个数字a,b求出[a,b]中转化成二进制后0的个数大于等于1的个数的数 例如1100转化成10-11,100-111,1000-1011,1100.保证每个区段都有1打头,然后有一段数字 ...
- asp.net 的那点事(2、浏览器和一般处理程序)
从今天开始我们接着来学习:asp.net中一般处理程序和浏览器的通信. 一.第一个图解: 从图解中我们看出,整个过程是:"请求---处理---响应".这个也就是经常面试的时候,面试 ...
- Webpack: 为Web开发而生的模块管理器[转]
Webpack: 为Web开发而生的模块管理器 原文地址:http://hanjianwei.com/2014/09/10/webpack-package-manager-for-web/ 10 Se ...