半小时速通【页面数据分页】

前端页面数据分页

导言

前端把每页的对象条数和当前页码发给后端,然后后端根据数值从数据库用SQL语句查询出来。

select * from t_table limit (pageNo - 1) * pageSize pageSize

涉及到要用三层架构的问题所以web层并不能直接和dao交互所以在交互的过程中还要建立page分页对象

效果大致是这样

首页 上一页 1 [2] 3 4 5 下一页 末页 共9页,18条记录 到第[input]页[确定] 

下面是整体思路

后端整体思路

一、建立page分页对象(bean层)

在分页对象中有五个属性,分别是

  • 当前页码
  • 每页的数据条数
  • 总页码
  • 总记录数(数据总条数)
  • 当前页的对象(考虑到代码复用的关系,用泛型)
public class Page<T> {

    public static final Integer PAGE_SIZE = 4;

    private Integer pageNo;//当前页码
    private Integer pageTotal;//总页码    pageTotalCount / pageSize  (+1)
    private Integer pageTotalCount;//总记录条数 select count(*) from table
    private Integer pageSize = PAGE_SIZE;//每页条数
    private List<T> items;//当前页的项

    /**
    getter 
    setter 
    constructor 
    toString
    */
}
  • 当前页码和每页的数据条数的确定的
  • 总记录数从数据库中查询
  • 总页数为
    • 总记录数 / 每页条数
    • 如果有余数 总页数+1
  • 每页 数据对象从数据库中查询,封闭成一个List集合

二、DAO层

  • 查询总记录数
  • 查询当前页的数据对象List集合

@Override
public Integer queryPageTotalCount() {
    String sql = "select count(*) from book;";
    Number number = (Number)queryForOneValue(sql);
    return number.intValue();
}

@Override
public List<Book> queryPageItems(Integer pageNo, Integer pageSize) {
    String sql = "select * from book limit ?,?";
    Integer begin = (pageNo - 1) * pageSize;
    Integer length = pageSize;

    List list = queryForList(Book.class,sql, begin, length);

    return list;
}

三、service层

  • 调用DAO层得到总记录数、当前页的数据对象List集合
  • 确定的当前的页码、每页的数据条数
  • 计算出总页数
  • 封闭成一个page分页bean对象

private BookDao bookDao = new BookDaoImpl();

@Override
public Page<Book> pageQueryForPrice(Integer pageNo, Integer pageSize, Integer min, Integer max) {
    // 求出总记录条数
    Integer pageTotalCount =  bookDao.queryPageTotalCountForPrice(min,max);
    // 求出总页码
    Integer pageTotal = pageTotalCount / pageSize;
    if(pageTotalCount % pageSize > 0) {
        pageTotal++;
    }

    // 数据边界
    if(pageNo < 1) {
        pageNo = 1;
    } else if(pageNo > pageTotal) {
        pageNo = pageTotal;
    }

    List<Book> books = bookDao.queryPageItemsForPrice(pageNo, pageSize,min,max);

    Page<Book> bookPage = new Page<>(pageNo,pageTotal,pageTotalCount,pageSize,books);

    return bookPage;
}

四、web层

  • 主要从前端接收请求
  • 调用service层得到page对象
  • 把当前的分页对象集合数据发给前端
  • 前端做显示

private BookService bookService = new BookServiceImpl();

/**
 * 分页显示图书
 * @param req
 * @param resp
 * @throws ServletException
 * @throws IOException
 */
protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String page = req.getParameter("page");
    Integer pageNo = Integer.valueOf(page);
    Integer pageSize = 4;

    Page<Book> pageBooks = bookService.page(pageNo, pageSize);

    req.setAttribute("page",pageBooks);

    req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);
}

前端(JSP+JSTL)

首页、上一页、下一页、末页

  • 首页就是1
  • 末页就是总页码数
  • 下一页是当前页+1
  • 上一页是当前页-1
  • 为防止用户调皮,要对每个项做隐性处理
    • 如果当前页为第一页,首页和上一页不能用
    • 如果当前页是最后一页,末页和下一页不能用
  • 加上不能选中复制的样式,提升体验
    • style="user-select: none
  • 对总记录数和总页码显示
<div id="page_nav" style="user-select: none">
	<c:if test="${ requestScope.page.pageNo > 1}">
		<a href="bookServlet?action=page&page=1">首页</a>
		<a href="bookServlet?action=page&page=${ requestScope.page.pageNo - 1 }">上一页</a>
	</c:if>
	<c:if test="${ requestScope.page.pageNo <= 1}">
		首页
		上一页
	</c:if>
	
	<%--分页条位置--%>

	<c:if test="${ requestScope.page.pageNo < requestScope.page.pageTotal }">
		<a href="bookServlet?action=page&page=${ requestScope.page.pageNo + 1}">下一页</a>
		<a href="bookServlet?action=page&page=${ requestScope.page.pageTotal }">末页</a>
	</c:if>
	<c:if test="${ requestScope.page.pageNo >= requestScope.page.pageTotal}">
		下一页
		末页
	</c:if>
	共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
	到第<input value="" name="pn" id="pn_input"/>页
	<input id="searchPageBtn" type="button" value="确定">
</div>

页码跳转

<script type="text/javascript">
    window.onload = function () {
		document.getElementById("searchPageBtn").onclick = function () {
			var pageNo = document.getElementById("pn_input").value;
			window.location.href = "bookServlet?action=page&page=" + pageNo;
		}
	}
</script>

到第<input value="" name="pn" id="pn_input"/>页
<input id="searchPageBtn" type="button" value="确定">

页码条的显示

  • 当前页要在页码条的中间
  • 页码条为奇数
// 5条
1 2 [3] 4 5

// 7
1 2 3 [4] 5 6 7
1、如果总页码数 <= 分页条长度
  • 直接显示所有的分页条
  • 1 到 总页码(末页)
<c:when test="${ requestScope.page.pageTotal <= pageScope.PAGE_NO_LENGTH }">
    <c:forEach begin="1" end="${ requestScope.page.pageTotal }" var="i">
    	<c:if test="${ i == requestScope.page.pageNo }">
    		[${ i }]
    	</c:if>
    	<c:if test="${ i != requestScope.page.pageNo }">
    		<a href="bookServlet?action=page&page=${ i }">${ i }</a>
    	</c:if>
    </c:forEach>
</c:when>
2、如果总页码数 > 分页条长度
2.1、如果当前页<=前几页分页条中间数
  • 比如说分页条为1 2 3 4 5、中间是3
  • 当前页为1、2、3
  • [1] 2 3 4 5
  • 1 [2] 3 4 5
  • 1 2 [3] 4 5
  • 分页条的中间公式
    • 分页条长度 / 2 + 1
  • 比如 5 / 2 + 1 == 3
  • 显示1 到 分页条长度
<c:when test="${ requestScope.page.pageNo <= (pageScope.PAGE_NO_LENGTH / 2 + 1) }">
	<c:forEach begin="1" end="${ pageScope.PAGE_NO_LENGTH  }" var="i">
		<c:if test="${ i == requestScope.page.pageNo }">
			[${ i }]
		</c:if>
		<c:if test="${ i != requestScope.page.pageNo }">
			<a href="bookServlet?action=page&page=${ i }">${ i }</a>
		</c:if>
	</c:forEach>
</c:when>
2.2、如果当前页 >= 最后几页中间数
  • 比如总共10页、分页条长度是5
  • 最后为6 7 [8] 9 10、中间是8
  • 6 7 [8] 9 10
  • 6 7 8 [9] 10
  • 6 7 8 9 [10]
  • 最后几页中间数公式
    • 总页码数 - (分页条长度 / 2)
  • 10 - (5 / 2) = 8
  • 显示 总页数 - 分页条长度 + 1 到 总页数(末页)
<c:when test="${ requestScope.page.pageNo >= requestScope.page.pageTotal - (pageScope.PAGE_NO_LENGTH  / 2) }">
	<c:forEach begin="${ requestScope.page.pageTotal - (pageScope.PAGE_NO_LENGTH - 1) }" end="${ requestScope.page.pageTotal }" var="i">
		<c:if test="${ i == requestScope.page.pageNo }">
			[${ i }]
		</c:if>
		<c:if test="${ i != requestScope.page.pageNo }">
			<a href="bookServlet?action=page&page=${ i }">${ i }</a>
		</c:if>
	</c:forEach>
</c:when>
2.3、其它情况
  • 不满足上面两个的任一情况
  • 比如总共10页、分页条长度是5
  • 2 3 [4] 5 6
  • 3 4 [5] 6 7
  • 4 5 [6] 7 8
  • 5 6 [7] 8 9
  • 显示当前页 - (分页条长度 / 2) 到 当前页 + (分页条长度 / 2)
<c:otherwise>
	<c:forEach begin="${ requestScope.page.pageNo - (pageScope.PAGE_NO_LENGTH / 2) }" end="${ requestScope.page.pageNo + (pageScope.PAGE_NO_LENGTH / 2)  }" var="i">
		<c:if test="${ i == requestScope.page.pageNo }">
			[${ i }]
		</c:if>
		<c:if test="${ i != requestScope.page.pageNo }">
			<a href="bookServlet?action=page&page=${ i }">${ i }</a>
		</c:if>
	</c:forEach>
</c:otherwise>

整体代码

  • 在EL表达式中两个整数相除结果会自动转成小数类型
  • 因为页条长度是奇数
  • 所以,每次 /2 时先 -1
<%!
	public static final int PAGE_NO_LENGTH = 5;
%>
<%
	pageContext.setAttribute("PAGE_NO_LENGTH",PAGE_NO_LENGTH);
%>
<div id="page_nav" style="user-select: none">
	<c:if test="${ requestScope.page.pageNo > 1}">
		<a href="bookServlet?action=page&page=1">首页</a>
		<a href="bookServlet?action=page&page=${ requestScope.page.pageNo - 1 }">上一页</a>
	</c:if>
	<c:if test="${ requestScope.page.pageNo <= 1}">
		首页
		上一页
	</c:if>
<%--		分页条--%>
	<c:choose>
<%--			如果总页码小于5   1,2,3,4,5  1,2,3,4  --%>
		<c:when test="${ requestScope.page.pageTotal <= pageScope.PAGE_NO_LENGTH }">
			<c:forEach begin="1" end="${ requestScope.page.pageTotal }" var="i">
				<c:if test="${ i == requestScope.page.pageNo }">
					[${ i }]
				</c:if>
				<c:if test="${ i != requestScope.page.pageNo }">
					<a href="bookServlet?action=page&page=${ i }">${ i }</a>
				</c:if>
			</c:forEach>
		</c:when>
		<c:when test="${ requestScope.page.pageTotal > pageScope.PAGE_NO_LENGTH }"><%-- 页码大于5  --%>

			<c:choose>
				<%--				pageno<=3    1,2,[3],4,5  --%>
				<c:when test="${ requestScope.page.pageNo <= ((pageScope.PAGE_NO_LENGTH - 1) / 2 + 1) }">
					<c:forEach begin="1" end="${ pageScope.PAGE_NO_LENGTH  }" var="i">
						<c:if test="${ i == requestScope.page.pageNo }">
							[${ i }]
						</c:if>
						<c:if test="${ i != requestScope.page.pageNo }">
							<a href="bookServlet?action=page&page=${ i }">${ i }</a>
						</c:if>
					</c:forEach>
				</c:when>

				<%--				pageno>pagetotal - 3    6,7,[8],9,10 --%>
				<c:when test="${ requestScope.page.pageNo >= requestScope.page.pageTotal - ((pageScope.PAGE_NO_LENGTH - 1) / 2) }">
					<c:forEach begin="${ requestScope.page.pageTotal - (pageScope.PAGE_NO_LENGTH - 1) }" end="${ requestScope.page.pageTotal }" var="i">
						<c:if test="${ i == requestScope.page.pageNo }">
							[${ i }]
						</c:if>
						<c:if test="${ i != requestScope.page.pageNo }">
							<a href="bookServlet?action=page&page=${ i }">${ i }</a>
						</c:if>
					</c:forEach>
				</c:when>

				<%--				否则    2,3,[4],5,6  --%>
				<c:otherwise>
					<c:forEach begin="${ requestScope.page.pageNo - ((pageScope.PAGE_NO_LENGTH - 1) / 2) }" end="${ requestScope.page.pageNo + ((pageScope.PAGE_NO_LENGTH - 1) / 2)  }" var="i">
						<c:if test="${ i == requestScope.page.pageNo }">
							[${ i }]
						</c:if>
						<c:if test="${ i != requestScope.page.pageNo }">
							<a href="bookServlet?action=page&page=${ i }">${ i }</a>
						</c:if>
					</c:forEach>
				</c:otherwise>

			</c:choose>

		</c:when>
	</c:choose>

	<c:if test="${ requestScope.page.pageNo < requestScope.page.pageTotal }">
		<a href="bookServlet?action=page&page=${ requestScope.page.pageNo + 1}">下一页</a>
		<a href="bookServlet?action=page&page=${ requestScope.page.pageTotal }">末页</a>
	</c:if>
	<c:if test="${ requestScope.page.pageNo >= requestScope.page.pageTotal}">
		下一页
		末页
	</c:if>
	共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录
	到第<input value="" name="pn" id="pn_input"/>页
	<input id="searchPageBtn" type="button" value="确定">
</div>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值