整个项目源代码可以到我的github上下载。前五个部分我们已经完成了用户的注册与登录模块,以及后台的图书管理,第六部分我们完成图书的分页部分,分页的原因就是一页显示全部信息太繁杂了,所以需要需要分页来解决这个问题。
分页模块的分析
分页模型Page的抽取 由分页的视图分析出分页的对象模型Page
类有如下属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public class Page <T > { public static final Integer PAGE_SIZE = 4 ; private Integer pageNo; private Integer pageTotal; private Integer pageSize = PAGE_SIZE; private Integer pageTotalCount; private List<Book> items;
分页的初步实现 BookDao
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 @Override public Integer queryForPageTotalCount () { String sql = "select count(*) from t_book" ; Number count = (Number) queryForSingleValue(sql); return count.intValue(); } @Override public List<Book> queryForPageItems (int begin, int pageSize) { String sql = "select `id`,`name`,`author`,`price`,`sales`,`stock`,`img_path` imgPath" + " from t_book limit ?,?" ; return queryForList(Book.class, sql, begin, pageSize); }
BookService
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Override public Page<Book> page (int pageNo, int pageSize) { Page<Book> page = new Page<Book>(); page.setPageNo(pageNo); page.setPageSize(pageSize); Integer pageTotalCount = bookDao.queryForPageTotalCount(); page.setPageTotalCount(pageTotalCount); Integer pageTotal = pageTotalCount / pageSize; if (pageTotalCount % pageSize > 0 ){ pageTotal+=1 ; } page.setPageTotal(pageTotal); int begin = (page.getPageNo() - 1 ) * pageSize; List<Book> items = bookDao.queryForPageItems(begin, pageSize); page.setItems(items); return page; }
BookServlet
程序的代码
1 2 3 4 5 6 7 8 9 10 11 protected void page (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int pageNo = WebUtils.parseInt(req.getParameter("pageNo" ), 1 ); int pageSize = WebUtils.parseInt(req.getParameter("pageSize" ), Page.PAGE_SIZE); Page<Book> page = bookService.page(pageNo, pageSize); req.setAttribute("page" , page); req.getRequestDispatcher("/pages/manager/book_manager.jsp" ).forward(req,resp); }
manager_menu.jsp
中图书管理请求地址的修改book_manager.jsp
修改
首页,上一页,下一页,末页实现 修改book_manager.jsp
实现跳到指定页数 修改book_manager.jsp
,通过绑定单击事件实现跳到指定页数Page
对象的修改,完成数据边界的有效检查,使其不会跳到没有的页数
1 2 3 4 5 6 7 8 9 10 public void setPageNo (Integer pageNo) {if (pageNo < 1 ) {pageNo = 1 ; } if (pageNo > pageTotal) {pageNo = pageTotal; } this .pageNo = pageNo;}
与之对应,要修改 BookService
中page
方法,因为设置当前页码时,需要 pageTotal
来进行数据边界的有效检查,所以设置当前页码要放在设置总页码之后。
页码的显示 一般来说,显示页码的时候,不仅会显示当前页的页码,还会显示前几页的页码,以及后几页的页码,然后点击这些页码就可以跳转到指定页。 这里实现一次显示5个页码,下面分情况讨论:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 情况1 : 如果总页码小于等于5 ,页码的范围是:1 ~总页码 1 页 1 2 页 1 ,2 3 页 1 ,2 ,3 4 页 1 ,2 ,3 ,4 5 页 1 ,2 ,3 ,4 ,5 情况2 : 总页码大于5 的情况。假设一共10 页 小情况1 :当前页码为前面2 个,页码的范围是:1 ~5 [1 ],2 ,3 ,4 ,5 1 ,[2 ],3 ,4 ,5 小情况2 :当前页码为最后2 个,页码的范围是:总页码-4 ~总页码 6 ,7 ,8 ,[9 ],10 6 ,7 ,8 ,9 ,[10 ] 小情况3 :其它情况,页码的范围是:当前页码-2 ~当前页码+2 2 ,3 ,[4 ],5 ,6 3 ,4 ,[5 ],6 ,7
按照上面的情况修改 book_manager.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <c:choose> <%--情况1 :如果总页码小于等于5 --%> <c:when test ="${ requestScope.page.pageTotal <=5 }" > <c:set var ="begin" value ="1" /> <c:set var ="end" value ="${requestScope.page.pageTotal}" /> </c:when > <%--情况2 :总页码大于5 的情况--%> <c:when test ="${requestScope.page.pageTotal > 5}" > <c:choose > <%--小情况1:当前页码为前面2个--%> <c:when test ="${requestScope.page.pageNo < 3}" > <c:set var ="begin" value ="1" /> <c:set var ="end" value ="5" /> </c:when > <%--小情况2:当前页码为最后2个--%> <c:when test ="${requestScope.page.pageNo > requestScope.page.pageTotal-2}" > <c:set var ="begin" value ="${requestScope.page.pageTotal-4}" /> <c:set var ="end" value ="${requestScope.page.pageTotal}" /> </c:when > <%--小情况3:其他情况--%> <c:otherwise > <c:set var ="begin" value ="${requestScope.page.pageNo-2}" /> <c:set var ="end" value ="${requestScope.page.pageNo+2}" /> </c:otherwise > </c:choose > </c:when > </c:choose>
1 2 3 4 5 6 7 8 <c:forEach begin="${begin}" end="${end}" var ="i" > <c:if test ="${ i == requestScope.page.pageNo }" > 【${i}】 </c:if > <c:if test ="${ i != requestScope.page.pageNo }" > <a href ="manager/bookServlet?action=page&pageNo=${i}" > ${i}</a > </c:if > </c:forEach>
修改分页后,增加,删除,修改图书信息的回显页面 以修改图书为例 1.在修改的请求地址上追加当前页码参数 2. 在book_edit.jsp
页面中使用隐藏域记录下pageNo
参数
在服务器重定向时,获取当前页码追加上进行跳转
首页index.jsp的跳转 因为首页也需要分页,所以我们访问首页的时候需要让其通过 ClientBookServlet
程序让其跳转到 web目录/pages/client目录的/index.jsp
创建ClientBookServlet
程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.atguigu.web;import com.atguigu.pojo.Book;import com.atguigu.pojo.Page;import com.atguigu.service.BookService;import com.atguigu.service.impl.BookServiceImpl;import com.atguigu.utils.WebUtils;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class ClientBookServlet extends BaseServlet { private BookService bookService = new BookServiceImpl(); protected void page (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int pageNo = WebUtils.parseInt(req.getParameter("pageNo" ), 1 ); int pageSize = WebUtils.parseInt(req.getParameter("pageSize" ), Page.PAGE_SIZE); Page<Book> page = bookService.page(pageNo, pageSize); page.setUrl("client/bookServlet?action=page" ); req.setAttribute("page" , page); req.getRequestDispatcher("/pages/client/index.jsp" ).forward(req,resp); } }
配置web.xml
,增加ClientBookServlet
的映射
1 2 3 4 5 6 7 8 <servlet > <servlet-name > ClientBookServlet</servlet-name > <servlet-class > com.atguigu.web.ClientBookServlet</servlet-class > </servlet > <servlet-mapping > <servlet-name > ClientBookServlet</servlet-name > <url-pattern > /client/bookServlet</url-pattern > </servlet-mapping >
创建client/index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>书城首页</title> <link type="text/css" rel="stylesheet" href="static/css/style.css" > </head> <body> <div id="header"> <img class="logo_img" alt="" src="static/img/logo.gif" > <span class="wel_word">网上书城</span> <div> <a href="pages/user/login.jsp">登录</a> <a href="pages/user/regist.jsp">注册</a> <a href="pages/cart/cart.jsp">购物车</a> <a href="pages/manager/manager.jsp">后台管理</a> </div> </div> <div id="main"> <div id="book"> <div class="book_cond"> <form action="" method="get"> 价格:<input id="min" type="text" name="min" value=""> 元 - <input id="max" type="text" name="max" value=""> 元 <input type="submit" value="查询" /> </form> </div> <div style="text-align: center"> <span>您的购物车中有3件商品</span> <div> 您刚刚将<span style="color: #ff0000">时间简史</span>加入到了购物车中 </div> </div> <c:forEach items="${requestScope.page.items}" var="book"> <div class="b_list"> <div class="img_div"> <img class="book_img" alt="" src="${book.imgPath}" /> </div> <div class="book_info"> <div class="book_name"> <span class="sp1">书名:</span> <span class="sp2">${book.name}</span> </div> <div class="book_author"> <span class="sp1">作者:</span> <span class="sp2">${book.author}</span> </div> <div class="book_price"> <span class="sp1">价格:</span> <span class="sp2">¥${book.price}</span> </div> <div class="book_sales"> <span class="sp1">销量:</span> <span class="sp2">${book.sales}</span> </div> <div class="book_amount"> <span class="sp1">库存:</span> <span class="sp2">${book.stock}</span> </div> <div class="book_add"> <button>加入购物车</button> </div> </div> </div> </c:forEach> </div> <div id="page_nav"> <a href="#">首页</a> <a href="#">上一页</a> <a href="#">3</a> 【4】 <a href="#">5</a> <a href="#">下一页</a> <a href="#">末页</a> 共10页,30条记录 到第<input value="4" name="pn" id="pn_input"/>页 <input type="button" value="确定"> </div> </div> <div id="bottom"> <span> 尚硅谷书城.Copyright ©2015 </span> </div> </body> </html>
修改web/index.jsp
为请求转发到Servlet
1 2 3 4 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%--只负责请求转发--%> <jsp:forward page ="/client/bookServlet?action=page" > </jsp:forward >
分页条的抽取 前台页面也需要分页条,因为对于分页条而言,只是请求的 url
不同,我们可以给 page
添加 url
属性,再把分页条抽取出来,就可以简单的调用分页条。
在 page
对象中添加 url
属性
在 Servlet
程序中的 page
分页方法中设置 url
的分页请求地址
修改分页条中请求地址为url
变量输出,并抽取一个单独的page_nav.jsp
页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <div id ="page_nav" > <c:choose > <%--情况1:如果总页码小于等于5--%> <c:when test ="${ requestScope.page.pageTotal <=5 }" > <c:set var ="begin" value ="1" /> <c:set var ="end" value ="${requestScope.page.pageTotal}" /> </c:when > <%--情况2:总页码大于5的情况--%> <c:when test ="${requestScope.page.pageTotal > 5}" > <c:choose > <%--小情况1:当前页码为前面2个--%> <c:when test ="${requestScope.page.pageNo < 3}" > <c:set var ="begin" value ="1" /> <c:set var ="end" value ="5" /> </c:when > <%--小情况2:当前页码为最后2个--%> <c:when test ="${requestScope.page.pageNo > requestScope.page.pageTotal-2}" > <c:set var ="begin" value ="${requestScope.page.pageTotal-4}" /> <c:set var ="end" value ="${requestScope.page.pageTotal}" /> </c:when > <%--小情况3:其他情况--%> <c:otherwise > <c:set var ="begin" value ="${requestScope.page.pageNo-2}" /> <c:set var ="end" value ="${requestScope.page.pageNo+2}" /> </c:otherwise > </c:choose > </c:when > </c:choose > <%--大于首页,才显示--%> <c:if test ="${requestScope.page.pageNo > 1}" > <a href ="${requestScope.page.url}&pageNo=1" > 首页</a > <a href ="${requestScope.page.url}&pageNo=${requestScope.page.pageNo-1}" > 上一页</a > </c:if > <c:forEach begin ="${begin}" end ="${end}" var ="i" > <c:if test ="${ i == requestScope.page.pageNo }" > 【${i}】 </c:if > <c:if test ="${ i != requestScope.page.pageNo }" > <a href ="${requestScope.page.url}&pageNo=${i}" > ${i}</a > </c:if > </c:forEach > <%--如果已经是最后一页,则不显示下一页,末页--%> <c:if test ="${requestScope.page.pageNo < requestScope.page.pageTotal}" > <a href ="${requestScope.page.url}&pageNo=${requestScope.page.pageNo+1}" > 下一页</a > <a href ="${requestScope.page.url}&pageNo=${requestScope.page.pageTotal}" > 末页</a > </c:if > 共${ requestScope.page.pageTotal }页,${ requestScope.page.pageTotalCount }条记录 到第<input value ="${param.pageNo}" name ="pn" id ="pn_input" /> 页 <input id ="searchPageBtn" type ="button" value ="确定" > <script type ="text/javascript" > $(function ( ) { $("#searchPageBtn" ).click(function ( ) { var pageNo = $("#pn_input" ).val(); <%--var pageTotal = ${requestScope.page.pageTotal};--%> location.href = "${pageScope.basePath}${requestScope.page.url}&pageNo=" + pageNo; }); }); </script > </div >
静态包含page_nav.jsp
首页价格搜索 BookDao
程序添加如下方法
1 2 3 4 5 6 7 8 9 10 11 12 13 @Override public Integer queryForPageTotalCountByPrice (int min, int max) { String sql = "select count(*) from t_book where price between ? and ?" ; Number count = (Number) queryForSingleValue(sql, min, max); return count.intValue(); } @Override public List<Book> queryForPageItemsByPrice (int begin, int pageSize, int min, int max) { String sql = "select `id`,`name`,`author`,`price`,`sales`,`stock`,`img_path` imgPath" + " from t_book where price between ? and ? limit ?,?" ; return queryForList(Book.class, sql, min, max, begin, pageSize); }
BookService
程序添加如下方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Override public Page<Book> pageByPrice (int pageNo, int pageSize, int min, int max) { Page<Book> page = new Page<Book>(); page.setPageSize(pageSize); Integer pageTotalCount = bookDao.queryForPageTotalCountByPrice(min,max); page.setPageTotalCount(pageTotalCount); Integer pageTotal = pageTotalCount / pageSize; if (pageTotalCount % pageSize > 0 ){ pageTotal+=1 ; } page.setPageTotal(pageTotal); page.setPageNo(pageNo); int begin = (page.getPageNo() - 1 ) * pageSize; List<Book> items = bookDao.queryForPageItemsByPrice(begin, pageSize, min, max); page.setItems(items); return page; }
ClientBookServlet
程序添加如下方法,需要注意的是设置 url
需要加上 min
和 max
参数,这样之后点击下一页之类的,才是按价格查询的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 protected void pageByPrice (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int pageNo = WebUtils.parseInt(req.getParameter("pageNo" ), 1 ); int pageSize = WebUtils.parseInt(req.getParameter("pageSize" ), Page.PAGE_SIZE); int min = WebUtils.parseInt(req.getParameter("min" ), 0 ); int max = WebUtils.parseInt(req.getParameter("max" ), Integer.MAX_VALUE); Page<Book> page = bookService.pageByPrice(pageNo, pageSize, min, max); StringBuilder sb = new StringBuilder("client/bookServlet?action=pageByPrice" ); if (req.getParameter("min" ) != null ) { sb.append("&min=" ).append(req.getParameter("min" )); } if (req.getParameter("max" ) != null ) { sb.append("&max=" ).append(req.getParameter("max" )); } page.setUrl(sb.toString()); req.setAttribute("page" , page); req.getRequestDispatcher("/pages/client/index.jsp" ).forward(req,resp); }