1.模型分析
2.实现分析
点击页码,传递参数,跳转到Servlet程序,处理分页操作,web层接收参数,调用Service层方法,获取Page对象,保存到request域中,请求转发并回显信息。
Service层调用Dao层处理分页业务,Dao层用SQL语句操作数据库,获取图书信息。
Page对象:
public static final Integer PAGE_SIZE = 4;
//当前页码
private Integer pageNo;
//总页数
private Integer pageTotal;
//当前页显示数量
private Integer pageSize = PAGE_SIZE;
//总记录数
private Integer pageTotalCount;
//当前页数据
private List<T> items;
BookServlet:
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);
//调用bookService
Page<Book> page = bookService.page(pageNo,pageSize);
//保存page对象到Request域中
req.setAttribute("page",page);
//请求转发
req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);
}
BookServiceImpl:
@Override
public Page<Book> page(int pageNo, int pageSize) {
Page<Book> page = new Page<Book>();
// 设置每页显示的数量
page.setPageSize(pageSize);
// 求总记录数
Integer pageTotalCount = bookDao.queryForPageTotalCount();
// 设置总记录数
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.queryForPageItems(begin,pageSize);
// 设置当前页数据
page.setItems(items);
return page;
}
BookDaoImpl:
@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);
}
book_mananger.jsp:
接收域中信息,回显数据。
<c:forEach items="${requestScope.page.items}" var="book">
<tr>
<td>${book.name}</td>
<td>${book.price}</td>
<td>${book.author}</td>
<td>${book.sales}</td>
<td>${book.stock}</td>
<td><a href="manager/bookServlet?action=getBook&id=${book.id}&pageNo=${requestScope.page.pageNo}">修改</a></td>
<!--传递总页数参数 -->
<td><a class="deleteClass" href="manager/bookServlet?action=delete&id=${book.id}&pageNo=${requestScope.page.pageNo}">删除</a></td>
</tr>
</c:forEach>
<div id="page_nav">
<a href="#">首页</a>
<a href="#">上一页</a>
<a href="#">3</a>
【${requestScope.Page.pageNo}】
<a href="#">5</a>
<a href="#">下一页</a>
<a href="#">末页</a>
共${requestScope.Page.pageTotal}页,${requestScope.Page.pageTotalCount}条记录
到第<input value="4" name="pn" id="pn_input"/>页
<input type="button" value="确定">
</div>
首页,下一页,上一页:
<div id="page_nav">
<%--大于首页,才显示--%>
<c:if test="${requestScope.page.pageNo > 1}">
<a href="manager/bookServlet?action=page&pageNo=1">首页</a>
<a href="manager/bookServlet?action=page&pageNo=${requestScope.Page.pageNo-1}">上一页</a>
</c:if>
<a href="#">3</a>
【${requestScope.Page.pageNo}】
<a href="#">5</a>
<%-- 如果已经 是最后一页,则不显示下一页,末页 --%>
<c:if test="${requestScope.page.pageNo < requestScope.page.pageTotal}">
<a href="manager/bookServlet?action=page&pageNo=${requestScope.Page.pageNo+1}">下一页</a>
<a href="manager/bookServlet?action=page&pageNo=${requestScope.Page.pageTotal}">末页</a>
</c:if>
共${requestScope.Page.pageTotal}页,${requestScope.Page.pageTotalCount}条记录
到第<input value="4" name="pn" id="pn_input"/>页
<input type="button" value="确定">
</div>
跳转到指定页码:
到第<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};--%>
<%--alert(pageTotal);--%>
// javaScript语言中提供了一个location地址栏对象
// 它有一个属性叫href.它可以获取浏览器地址栏中的地址
// href属性可读,可写
//赋值,页面跳转
location.href = "${pageScope.basePath}${ requestScope.page.url }&pageNo=" + pageNo;
});
});
</script>
数据边界:
public void setPageNo(Integer pageNo) {
/*数据边界的有效检查*/
if (pageNo < 1){
pageNo = 1;
}
if (pageNo > pageTotal){
pageNo = pageTotal;
}
this.pageNo = pageNo;
}
分页模块中,页码 1,2,【3】,4,5 的显示,要显示 5 个页 码,并且页码可以点击跳转:
需求:显示 5 个连续的页码,而且当前页码在中间。除了当前页码之外,每个页码都可以点击跳到指定页。
情况 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:当前页码为前面 3 个:1,2,3 的情况,页码范围是:1-5.
【1】2,3,4,5
1【2】3,4,5
1,2【3】4,5
小情况 2:当前页码为最后 3 个,8,9,10,页码范围是:总页码减 4 - 总页码
6,7【8】9,10
6,7,8【9】10
6,7,8,9【10】
小情况 3:4,5,6,7,页码范围是:当前页码减 2 - 当前页码加 2
2,3,4,5,6
3,4,5,6,7
4,5,6,7,8
5,6,7,8,9
修改分页后,增加,删除,修改图书信息的回显页面:
在mananger_jsp页面中 向 book_edit页面传递信息
<!--传递当前页数参数 -->
<td><a href="manager/bookServlet?action=getBook&id=${book.id}&pageNo=${requestScope.page.pageNo}">修改</a></td>
<td><a class="deleteClass" href="manager/bookServlet?action=delete&id=${book.id}&pageNo=${requestScope.page.pageNo}">删除</a></td>
<!--传递总页数参数 -->
<td><a href="pages/manager/book_edit.jsp?pageNo=${requestScope.page.pageTotal}">添加图书</a></td>
在book_edit页面点击提交时,提交给BookServlet,BookServlet调用对于方法处理请求
protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int pageNo = WebUtils.parseInt(req.getParameter("pageNo"),0);
pageNo += 1;
// 1、获取请求的参数==封装成为Book对象
Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
// 2、调用BookService.addBook()保存图书
bookService.addBook(book);
// 3、跳到图书列表页面
// /manager/bookServlet?action=list
// req.getRequestDispatcher("/manager/bookServlet?action=list").forward(req, resp);
//跳转到最后一页
resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo=" + pageNo);
}
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数id,图书编程
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 2、调用bookService.deleteBookById();删除图书
bookService.deleteBookById(id);
// 3、重定向回图书列表管理页面
// /book/manager/bookServlet?action=list
resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo=" + req.getParameter("pageNo"));
}
protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取请求的参数==封装成为Book对象
Book book = WebUtils.copyParamToBean(req.getParameterMap(),new Book());
// 2、调用BookService.updateBook( book );修改图书
bookService.updateBook(book);
// 3、重定向回图书列表管理页面
// 地址:/工程名/manager/bookServlet?action=list
resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo="+ req.getParameter("pageNo"));
}
首页 index.jsp 的跳转:
分页条的抽取:
抽取分页条中请求地址为 url 变量:
1.在 page 对象中添加 url 属性
// 分页条的请求地址 private String url;
2.在 Servlet 程序的 page 分页方法中设置 url 的分页请求地址
传递url值
在BookServlet中
page.setUrl("manager/bookServlet?action=page");
在ClientBookServlet中
page.setUrl("client/bookServlet?action=page");
3.修改分页条中请求地址为 url 变量输出,并抽取一个单独的 jsp 页面
在common中新建page_nav.jsp页面
接收url的值,作为跳转位置
%--分页条的开始--%>
<div id="page_nav">
<%--大于首页,才显示--%>
<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:choose>
<%--情况1:如果总页码小于等于5的情况,页码的范围是:1-总页码--%>
<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:当前页码为前面3个:1,2,3的情况,页码范围是:1-5.--%>
<c:when test="${requestScope.page.pageNo <= 3}">
<c:set var="begin" value="1"/>
<c:set var="end" value="5"/>
</c:when>
<%--小情况2:当前页码为最后3个,8,9,10,页码范围是:总页码减4 - 总页码--%>
<c:when test="${requestScope.page.pageNo > requestScope.page.pageTotal-3}">
<c:set var="begin" value="${requestScope.page.pageTotal-4}"/>
<c:set var="end" value="${requestScope.page.pageTotal}"/>
</c:when>
<%--小情况3:4,5,6,7,页码范围是:当前页码减2 - 当前页码加2--%>
<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: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>
<%--页码输出的结束--%>
首页价格搜索:
ClientBookServlet pageByPrice方法:
从index.jsp页面中获取请求参数,pageNo,pagaSize,min,max。调用bookService,查询并封装为page对象,并设置URL。再请求转发到index.jsp页面。page_nav.jsp页面接收url的值,作为页码跳转位置。page_nav.jsp页面接收page对象,遍历并显示数据。
/**
* 处理分页功能
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void pageByPrice(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1 获取请求的参数 pageNo 和 pageSize
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);
//2 调用BookService.page(pageNo,pageSize):Page对象
Page<Book> page = bookService.pageByPrice(pageNo,pageSize,min,max);
//设置URL地址的时候要带上价格区间
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());
//3 保存Page对象到Request域中
req.setAttribute("page",page);
//4 请求转发到pages/manager/book_manager.jsp页面
req.getRequestDispatcher("/pages/client/index.jsp").forward(req,resp);
}
}
查询价格区间并回显区间数据:
<form action="client/bookServlet" method="get">
<input type="hidden" name="action" value="pageByPrice">
价格:<input id="min" type="text" name="min" value="${param.min}"> 元 -
<input id="max" type="text" name="max" value="${param.max}"> 元
<input type="submit" value="查询" />
</form>