网 上 书 城

1.5创建BookManagerServlet

  • bookList() → 获取图书列表的方法
  • addBook() → 添加图书的方法
  • deleteBook() → 删除图书的方法
  • editBook() → 编辑图书的方法
  • saveOrUpdate() → 保存或者更新图书的方法
  • 修改图书操作
    • 当我们点击修改图书时,首先我们需要根据当前图书的ID去数据库中将该图书的信息查询出来显示到编辑图书的页面jsp。
      • editBook() → 通过ID从数据库中查询到该图书显示到jsp页面。
    • 当修改完图书之后我们需要把修改之后的图书信息提交到一个更新图书的方法中去,不过这个时候我们添加图书和修改图书的页面都是bookjsp,那么我们怎么判断我们是在添加图书还是在修改图书呢
      • 方式一我们可以将添加图书和修改图书分离,再创建一个jsp页面
      • 方式二添加图书没有ID,但是修改图书有ID,所有我们可以通过是否有ID来判断当前是添加图书的操作还是修改图书的操作,不过我们需要把图书的ID放到一个隐藏域中。
        • 将之前的addBook()方法改为saveOrUpdate()方法,在该方法中通过判断获取的图书ID是否为null来决定是调用BookService的saveBook方法还是update()方法。

1.6添加分页

  • 至此,我们管理端图书的增删改查已经完成,但是我们在获取图书列表的方法中是将数据库中的所有图书都查询了出来,如果数据库中的图书过多在页面显示时就会出现滚动条,不但用户体验不好而且一次性从数据库中查询这么多条记录性能也差。所以我们需要对图书进行分页显示
    • 在sql语句中使用limit关键字进行分页
    • 我们知道我们从数据库中查询出来的图书放到了一个List集合中,但是如果添加分页操作我们需要知道总页数、当前页码、总记录数等信息,但是List中并没有这些信息,所有我们需要创建一个类来封装分页的信息

  • Page<T>类
  • private List<T> list; //从数据库中查询的集合
  • public static final int PAGE_SIZE=5; //每页显示多少条记录
  • private int pageNo; //当前页
  • private int totalPageNo; //总页数
  • private int totalRecord; //总记录数
  • 修改BookDao:添加一个分页的方法
    • Page<Book> getPageBook(Page<Book> page) → 分页查找图书的方法
      • 该方法由BookService调用,传过来一个带有pageNo的Page<Book> 类型的page参数,通过该方法从数据库中先获取总的记录数,然后通过page的(pageNo-1)*PAGE_SIZE和PAGE_SIZE获取一个带分页的List集合。给page设置了总的记录数和List后再将page返回。
    • 修改BookService:同样添加一个分页的方法
      • Page<Book> getPageBook(String pageNo) → 分页查找图书的方法
        • 该方法由Servlet调用,接受的请求参数都是String类型的,所以传入的页码pageNo设置为了字符串类型。实现该方法是首先要创建一个Page<Book>对象,然后设置pageNo属性,不过这里需要将获取的字符串类型的pageNo转换为int类型。注意有可能会出现转换异常(例如用户输入的是字符串abc)
      • 在BookManagerServlet中添加getPageBook()方法
      • 这时我们发现我们原来的bookList()已经没用了……
        • 就会导致原来添加图书、修改图书、删除图书出现bug。
        • 改完bug之后考虑一个问题:目前我们执行添加图书、删除图书、修改图书之后都回到了图书列表的首页,我们能不能让它回到执行之前的那个页面呢?(提示:我们可以通过请求头中的Referer获取之前的地址
      • 关于分页页码的问题
        • 目前我们是将所有的页面都显示了出来,如果页面过多则用户体验不好,我们能不能让它只显示5个页面呢?
        • 1234  5
        • 1 [2]  3  4  5
        • 1 2[3]  4  5
        • 2 3  [45  6
        • 3 4  [5]  6  7
        • 综上可知:一共有三种情况
          • 总页数小于5时
          • 总页数等于5,当前页小于等于3时
          • 总页数大于5,当前页大于3时

<!-- 设置两个变量 begin 和 end -->

<!-- 注意:当end大于总页数时这种情况 -->

<c:choose>

<c:when test="${page.totalPageNo < 5 }">

<c:set var="begin" value="1"></c:set>

<c:set var="end" value="${page.totalPageNo }"></c:set>

</c:when>

<c:when test="${page.pageNo <=3  }">

<c:set var="begin" value="1"></c:set>

<c:set var="end" value="5"></c:set>

</c:when>

<c:otherwise>

<c:set var="begin" value="${page.pageNo - 2 }"></c:set>

<c:set var="end" value="${page.pageNo + 2 }"></c:set>

<c:if test="${end > page.totalPageNo }">

<c:set var="begin" value="${page.totalPageNo - 4 }"></c:set>

<c:set var="end" value="${page.totalPageNo}"></c:set>

</c:if>

</c:otherwise>

</c:choose>

  • 分页完成之后如何复用分页
    • 使页码超链接的请求地址动态显示
      • 获取请求地址
      • 获取查询字符串
      • 将请求地址与查询字符串使用?拼接
      • 给Page类添加一个path属性,将拼接好的地址设置到page对象的path属性中