3、图书的分页:
3.1、page对象的创建
分析:
- 在 pojo 层中 创建表 page 类
/**
* Page是分页的模型对象
* @param <T> 是具体的模块的 javaBean类
*/
public class Page<T> {
public static final Integer PAGE_SIZE = 3;
//当前页码
private Integer pageNo;
//总页码
private Integer pageTotal;
//当前页面显示数量
private Integer pageSize = PAGE_SIZE;
//总记录数
private Integer pageToTalCount;
//当前页数据
private List<T> items;
}
将page 分页 类写出泛型,因为分页在很多页码都用得到,使用时直接实例化就行
3.2、Web层创建 page() 分页方法
到web层的 BookServlet 创建 page 方法 需要传递两个参数: pageNo(当前页) 和 pageSize(当前页的数量)
protected void page(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);
//2.调用BookService.page(pageNo,pageSize):page对象
Page<Book> page = bookService.page(pageNo,pageSize);
//3.保存Page对象到Request 域中
req.setAttribute("page",page);
//4.请求转发到 /pages/manager/book_manager.jsp
req.getRequestDispatcher("/pages/manager/book_manager.jsp?pageNo=" + req.getParameter("pageNo")).forward(req,resp);
//
}
- 分页需要book的信息,所以需要再创建一个方法 获取所有图书信息
protected void getBook(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取请求的参数图书编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
//2.调用bookService.queryBookById 查询图书
Book book = bookService.queryBookById(id);
//3.将图书信息保存到 request 域中
req.setAttribute("book",book);
//4.请求转发给 pages/manager/book_edit.jsp 页面
req.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(req,resp);
}
将获取到的图书信息保存到 Request域中
3.2、BookService层的实现和测试
- 在BookService 接口 添加 page方法
public interface BookService {
public void addBook(Book book);
public void deleteBookById(Integer id);
public void updateBook(Book book);
public Book queryBookById(Integer id);
public List<Book> queryBook();
Page<Book> page(int pageNo, int pageSize);
}
- 到 BookServiceImpl 重新 page 方法。
package com.aiguigu.service.impl;
import com.aiguigu.dao.BookDao;
import com.aiguigu.dao.UserDao;
import com.aiguigu.dao.impl.BookDaoImpl;
import com.aiguigu.dao.impl.UserDaoImpl;
import com.aiguigu.pojo.Book;
import com.aiguigu.pojo.Page;
import com.aiguigu.service.BookService;
import java.util.List;
public class BookServiceImpl implements BookService {
//Service 依赖于 Dao
private BookDao bookDao = new BookDaoImpl();
@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;
}
}
创建一个page对象 调用 set 方法 给 Page 类里的参数赋值
//求总记录数
Integer pageTotalCount = bookDao.queryForPageTotalCount();
设置当前页的数据:
需要一个方法获取当前页数据
queryForPageItems(begin,pageSize);
int begin = (page.getPageNo()-1)*pageSize;//第一页就是从0开始
3.3、BookDao层实现 在Service层写的方法
- BookDao 实现这两个方法的接口
`package com.aiguigu.dao;
import com.aiguigu.pojo.Book;
import java.util.List;
public interface BookDao {
Integer queryForPageTotalCount();
List<Book> queryForPageItems(int begin, int pageSize);
}
- BookDaoImpl 实现这两个方法
package com.aiguigu.dao.impl;
import com.aiguigu.dao.BookDao;
import com.aiguigu.pojo.Book;
import java.util.List;
public class BookDaoImpl extends BaseDao implements BookDao {
@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);
}
}
- 测试,先测Dao层,再测Service层,最后测 Web层
Dao层
public class BookDaoTest {
BookDao bookDao = new BookDaoImpl();
@Test
public void queryForPageTotalCount(){
System.out.println(bookDao.queryForPageTotalCount());
}
@Test
public void queryForPageItems(){
List<Book> books = bookDao.queryForPageItems(8, Page.PAGE_SIZE);
for(Book book : books){
System.out.println(book);
}
}
}
Service层
package com.aiguigu.test;
import com.aiguigu.pojo.Book;
import com.aiguigu.pojo.Page;
import com.aiguigu.service.BookService;
import com.aiguigu.service.impl.BookServiceImpl;
import org.junit.Test;
import java.math.BigDecimal;
import static org.junit.Assert.*;
public class BookServiceTest {
private BookService bookService = new BookServiceImpl();
@Test
public void page(){
System.out.println(bookService.page(1, Page.PAGE_SIZE));
}
}
Web层,将分页栏的内容动态输出
3.4、首页,上一页,末页的实现
<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>
<%-- 如果已经是最好一页,则不显示下一页和末页 --%>
<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="${param.pageNo}" name="pn" id="pn_input"/>页
<input id="searchPageBtn" type="button" value="确定">
</div>
3.5、跳到指定页码的实现
给确定按钮绑定点击事件
<div id="page_nav">
<input id="searchPageBtn" type="button" value="确定">
<script type="text/javascript">
$(function () {
$("#searchPageBtn").click(function () {
var pageNo = $("#pn_input").val();
//javaScript 语言提供了一个 location地址栏对象
//它有一个属性叫href,它可以获取浏览器中的地址
//href 属性可读,可写
location.href = "${pageContext.getAttribute("basepath")}manager/bookServlet?action=page&pageNo=" + pageNo;
});
});
</script>
</div>
3.6、分页条页码的输出
分析:
<%-- 页码输出的开始--%>
<c:choose>
<%--情况1,如果总页码小于等于5的情况,页码的范围是:1-总页码--%>
<c:when test="${requestScope.page.pageTotal <=5}">
<c:set var="begin" value="1"></c:set>
<c:set var="end" value="${requestScope.page.pageTotal}"></c:set>
</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>
<c:set var="end" value="5"></c:set>
</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>
<c:set var="end" value="${requestScope.page.pageTotal}"></c:set>
</c:when>
<%--小情况3:4,5,6,7,页码范围是:当前页码减2 - 当前页码加2 --%>
<c:otherwise>
<c:set var="begin" value="${requestScope.page.pageNo-2}"></c:set>
<c:set var="end" value="${requestScope.page.pageNo+2}"></c:set>
</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="manager/bookServlet?action=page&pageNo=${i}">${i}</a>
</c:if>
</c:forEach>
3.7、修改分页对原来,添加、删除、修改的影响
原来添加、删除、修改 的方法重定向是执行list方法
现在需要将执行list方法的地方改成执行 page方法
在book_manager.jsp页面中 添加、修改、删除的 a标签 的跳转页面 加入 执行方法 和 当前页 的参数
执行添加图书方法时,需要将当前页加1,防止 在客户端当前页已满再添加图书时不会定位到新添加图书的页面