书城项目的第五阶段

1、图书模块

1.1、编写图书模块的数据库表

CREATE TABLE t_book(
	`id` INT(11) PRIMARY KEY AUTO_INCREMENT, 	## 主键
	`name` VARCHAR(50) NOT NULL,				## 书名 
	`author` VARCHAR(50) NOT NULL,				## 作者
	`price` DECIMAL(11,2) NOT NULL,				## 价格
	`sales` INT(11) NOT NULL,					## 销量
	`stock` INT(11) NOT NULL,					## 库存
	`img_path` VARCHAR(200) NOT NULL			## 书的图片路径
);

## 插入初始化测试数据
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'java从入门到放弃' , '国哥' , 80 , 9999 , 9 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '数据结构与算法' , '严敏君' , 78.5 , 6 , 13 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '怎样拐跑别人的媳妇' , '龙伍' , 68, 99999 , 52 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '木虚肉盖饭' , '小胖' , 16, 1000 , 50 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'C++编程思想' , '刚哥' , 45.5 , 14 , 95 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '蛋炒饭' , '周星星' , 9.9, 12 , 53 , 'static/img/default.jpg');
 
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '赌神' , '龙伍' , 66.5, 125 , 535 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'Java编程思想' , '阳哥' , 99.5 , 47 , 36 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'JavaScript从入门到精通' , '婷姐' , 9.9 , 85 , 95 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'cocos2d-x游戏编程入门' , '国哥' , 49, 52 , 62 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'C语言程序设计' , '谭浩强' , 28 , 52 , 74 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'Lua语言程序设计' , '雷丰阳' , 51.5 , 48 , 82 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '西游记' , '罗贯中' , 12, 19 , 9999 , 'static/img/default.jpg');

INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '水浒传' , '华仔' , 33.05 , 22 , 88 , 'static/img/default.jpg');
 
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '操作系统原理' , '刘优' , 133.05 , 122 , 188 , 'static/img/default.jpg');
 
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '数据结构 java版' , '封大神' , 173.15 , 21 , 81 , 'static/img/default.jpg');
 
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'UNIX高级环境编程' , '乐天' , 99.15 , 210 , 810 , 'static/img/default.jpg');
 
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , 'javaScript高级编程' , '国哥' , 69.15 , 210 , 810 , 'static/img/default.jpg');
 
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '大话设计模式' , '国哥' , 89.15 , 20 , 10 , 'static/img/default.jpg');
 
INSERT INTO t_book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`) 
VALUES(NULL , '人月神话' , '刚哥' , 88.15 , 20 , 80 , 'static/img/default.jpg');
 


## 查看表内容
SELECT id,NAME,author,price,sales,stock,img_path FROM t_book;

1.2、编写图书模块的 JavaBean

/**
 * @author acoffee
 * @create 2021-01-09 19:54
 */
public class Book {

    private Integer id;
    private String name;
    private String author;
    private BigDecimal price;
    private Integer sales;
    private Integer stock;
    private String imgPath="static/img/default.jpg";


    public Book() {
    }

    public Book(Integer id, String name, String author, BigDecimal price, Integer sales, Integer stock, String imgPath) {
        this.id = id;
        this.name = name;
        this.author = author;
        this.price = price;
        this.sales = sales;
        this.stock = stock;
        //要求给定的图片封面路径不能为空
        if (imgPath!=null&& !"".equals(imgPath)){
            this.imgPath = imgPath;
        }
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public Integer getSales() {
        return sales;
    }

    public void setSales(Integer sales) {
        this.sales = sales;
    }

    public Integer getStock() {
        return stock;
    }

    public void setStock(Integer stock) {
        this.stock = stock;
    }

    public String getImgPath() {
        return imgPath;
    }

    public void setImgPath(String imgPath) {
        this.imgPath = imgPath;
    }

    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", sales=" + sales +
                ", stock=" + stock +
                ", imgPath='" + imgPath + '\'' +
                '}';
    }
}

1.3、编写图书模块的 Dao 和测试 Dao

Dao 接口

public interface BookDao {

    public int addBook(Book book);

    public int deleteBookById(Integer id);

    public int updateBook(Book book);

    public Book queryBookById(Integer id);

    public List<Book> queryBooks();

}

BookDaoImpl 实现类:

public class BookDaoImpl extends BaseDao implements BookDao {
    @Override
    public int addBook(Book book) {
        String sql = "INSERT INTO t_book(`name`,`author`,`price`,`sales`,`stock`,`img_path`) values(?,?,?,?,?,?)";

        return update(sql, book.getName(), book.getAuthor(), book.getPrice(), book.getSales(), book.getStock(), book.getImgPath());
    }

    @Override
    public int deleteBookById(Integer id) {
        String sql = "delete from t_book where if = ?";
        return update(sql, id);
    }

    @Override
    public int updateBook(Book book) {
        String sql = "update t_book set `name`=?,`author`=?,`price`=?,`sales`=?,`stock`=?,`img_path`=? where id = ?";
        return update(sql, book.getName(), book.getAuthor(), book.getPrice(), book.getSales(), book.getStock(), book.getImgPath(), book.getId());
    }

    @Override
    public Book queryBookById(Integer id) {
        String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` from t_book where id = ?";
        return queryForOne(Book.class, sql, id);
    }

    @Override
    public List<Book> queryBooks() {
        String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` from t_book";
        return queryForList(Book.class, sql);
    }
}

1.4、编写图书模块的 Service 和测试 Service

BookService 接口

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> queryBooks();
}

BookServiceImpl 实现类:

public class BookDaoImpl extends BaseDao implements BookDao {
    @Override
    public int addBook(Book book) {
        String sql = "INSERT INTO t_book(`name`,`author`,`price`,`sales`,`stock`,`img_path`) values(?,?,?,?,?,?)";

        return update(sql, book.getName(), book.getAuthor(), book.getPrice(), book.getSales(), book.getStock(), book.getImgPath());
    }

    @Override
    public int deleteBookById(Integer id) {
        String sql = "delete from t_book where id = ?";
        return update(sql, id);
    }

    @Override
    public int updateBook(Book book) {
        String sql = "update t_book set `name`=?,`author`=?,`price`=?,`sales`=?,`stock`=?,`img_path`=? where id = ?";
        return update(sql, book.getName(), book.getAuthor(), book.getPrice(), book.getSales(), book.getStock(), book.getImgPath(), book.getId());
    }

    @Override
    public Book queryBookById(Integer id) {
        String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` from t_book where id = ?";
        return queryForOne(Book.class, sql, id);
    }

    @Override
    public List<Book> queryBooks() {
        String sql = "select `id` , `name` , `author` , `price` , `sales` , `stock` , `img_path` from t_book";
        return queryForList(Book.class, sql);
    }
}

BookService 的测试:

public class BookServiceTest {

    private BookService bookService = new BookServiceImpl();

    @Test
    public void addBook() {
        bookService.addBook(new Book(null,"火男刀锋","1123",new BigDecimal(100000),100000,0,null));
    }

    @Test
    public void deleteBookById() {
        bookService.deleteBookById(22);
    }

    @Test
    public void updateBook() {
        bookService.updateBook(new Book(22,"biubiu~~","1123",new BigDecimal(100000),100000,0,null));
    }

    @Test
    public void queryBookById() {
        System.out.println(bookService.queryBookById(20));
    }

    @Test
    public void queryBooks() {
        for (Book queryBook : bookService.queryBooks()) {
            System.out.println(queryBook);
        }
    }
}

1.5、编写图书模块的 Web 层,和页面联调测试

1.5.1、图书列表功能的实现

1、图解列表功能流程:
在这里插入图片描述
2、BookServlet 程序中添加 list 方法

	protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.通过BookServlet查询全部图书
        List<Book> books = bookService.queryBooks();

        //2.把全部图书保存到Request域中
        req.setAttribute("books",books);

        //3.请求转发到/pages/manager/book_manager.jsp页面
        req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp);
    }

3、修改【图书管理】请求地址
在这里插入图片描述
4、修改 pages/manager/book_manager.jsp 页面的数据遍历输出

<%@ 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>
    <%--静态包含 base标签 ,css样式--%>
    <%@ include file="/pages/common/head.jsp" %>
</head>
<body>

<div id="header">
    <img class="logo_img" alt="" src="../../static/img/logo.gif">
    <span class="wel_word">图书管理系统</span>
    <%--静态包含manager管理模块的菜单--%>
    <%@ include file="/pages/common/manager_menu.jsp" %>
</div>

<div id="main">
    <table>
        <tr>
            <td>名称</td>
            <td>价格</td>
            <td>作者</td>
            <td>销量</td>
            <td>库存</td>
            <td colspan="2">操作</td>
        </tr>

        <c:forEach items="${requestScope.books}" 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="book_edit.jsp">修改</a></td>
                <td><a href="#">删除</a></td>
            </tr>
        </c:forEach>

        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td><a href="book_edit.jsp">添加图书</a></td>
        </tr>
    </table>
</div>

<%--静态包含页脚内容--%>
<%@include file="/pages/common/footer.jsp" %>
</body>
</html>

1.5.2、前后台的简单介绍
在这里插入图片描述
1.5.3、添加图书功能的实现
1.5.3.1、添加图书流程细节:
在这里插入图片描述
1.5.3.2、问题说明:表单重复提交
当用户提交完请求,浏览器会记录下最后一次请求的全部信息。当用户按下功能键 F5,就会发起浏览器记录的最后一次请求。

1.5.3.3、BookServlet 程序中添加 add 方法

    protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取请求的参数==封装为Book对象
        Book book = WebUtils.copyParamToBean(req.getParameterMap(), new Book());

        //2.调用BookService.addBook()保存图书
        bookService.addBook(book);

        //3.跳到图书列表页面
        //   /manager/bookServlet?action=list
        resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");
    }

1.5.3.4、修改 book_edit.jsp 页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>编辑图书</title>
    <%--静态包含 base标签 ,css样式--%>
    <%@ include file="/pages/common/head.jsp" %>
    <style type="text/css">
        h1 {
            text-align: center;
            margin-top: 200px;
        }

        h1 a {
            color: red;
        }

        input {
            text-align: center;
        }
    </style>
</head>
<body>
<div id="header">
    <img class="logo_img" alt="" src="../../static/img/logo.gif">
    <span class="wel_word">编辑图书</span>
    <%--静态包含manager管理模块的菜单--%>
    <%@ include file="/pages/common/manager_menu.jsp" %>
</div>

<div id="main">
    <form action="manager/bookServlet" method="get">
        <input type="hidden" name="action" value="add">
        <table>
            <tr>
                <td>名称</td>
                <td>价格</td>
                <td>作者</td>
                <td>销量</td>
                <td>库存</td>
                <td colspan="2">操作</td>
            </tr>
            <tr>
                <td><input name="name" type="text" value="时间简史"/></td>
                <td><input name="price" type="text" value="30.00"/></td>
                <td><input name="author" type="text" value="霍金"/></td>
                <td><input name="sales" type="text" value="200"/></td>
                <td><input name="stock" type="text" value="300"/></td>
                <td><input type="submit" value="提交"/></td>
            </tr>
        </table>
    </form>


</div>

<%--静态包含页脚内容--%>
<%@include file="/pages/common/footer.jsp" %>
</body>
</html>

1.5.4、删除图书功能的实现
1.5.4.1、图解删除流程
在这里插入图片描述
1.5.4.2、BookServlet 程序中的 delete 方法:

    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=list");

    }

1.5.4.3、给 WebUtils 工具类添加转换 int 类型的工具方法

    /**
     * 将字符串转化称为int类型的数据
     * @param strInt
     * @param defaultValue
     * @return
     */
    public static int parseInt(String strInt,int defaultValue){

        try {
            return Integer.parseInt(strInt);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return defaultValue;
    }

1.5.4.4、修改删除的连接地址:
在这里插入图片描述
1.5.4.5、给删除添加确认提示操作:

<script type="text/javascript">

        $(function () {
            $("a.deleteClass").click(function () {
                // 在事件的function函数中,有一个this对象。这个this对象
                // 是当前正在响应事件的dom对象
                /**
                 * confirm是确认提示框函数
                 * 参数是它的提示内容
                 * 它有两个按钮,一个确认,应该是取消
                 * 返回true表示点击了,确认,返回false表示点击了取消
                 */
                return confirm("你确定要删除【"+$(this).parent().parent().find("td:first").text()+"】?");

            })
        });
    </script>

执行结果:在这里插入图片描述
1.5.5、修改图书功能的实现
1.5.5.1:图解修改图书细节:
在这里插入图片描述
1.5.5.2、更新【修改】的请求地址
在这里插入图片描述
1.5.5.3、BookServlet 程序中添加 getBook 方法:

    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);
    }

1.5.5.4、在 book_edit.jsp 页面中显示修改的数据

<div id="main">
    <form action="manager/bookServlet" method="get">
        <input type="hidden" name="action" value="add">
        <table>
            <tr>
                <td>名称</td>
                <td>价格</td>
                <td>作者</td>
                <td>销量</td>
                <td>库存</td>
                <td colspan="2">操作</td>
            </tr>
            <tr>
                <td><input name="name" type="text" value="${requestScope.book.name}"/></td>
                <td><input name="price" type="text" value="${requestScope.book.price}"/></td>
                <td><input name="author" type="text" value="${requestScope.book.author}"/></td>
                <td><input name="sales" type="text" value="${requestScope.book.sales}"/></td>
                <td><input name="stock" type="text" value="${requestScope.book.stock}"/></td>
                <td><input type="submit" value="提交"/></td>
            </tr>
        </table>
    </form>

1.5.5.5、在 BookServlet 程序中添加 update 方法:

    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=list");
    }

1.5.5.6、解决 book_edit.jsp 页面,即要实现添加,又要实现修改操作。
在这里插入图片描述

2、图书分页

2.1、分页模块的分析

在这里插入图片描述

2.2、分页模型 Page 的抽取(当前页数,总页数,总记录数, 当前页数据,每页记录数)

/**
 * page是分页的模型对象
 * <T>是具体的模块的javaBean类
 * @author acoffee
 * @create 2021-01-10 16:23
 */
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<T> items;

2.3、分页的初步实现

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` from t_book limit ?,?";
        return queryForList(Book.class,sql,begin,pageSize);
    }

BookService 代码:

   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 程序的代码:

    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").forward(req,resp);
    }

manager_menu.jsp 中【图书管理】请求地址的修改:
在这里插入图片描述
book_manager.jsp 修改:

<%@ 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>
    <%--静态包含 base标签 ,css样式--%>
    <%@ include file="/pages/common/head.jsp" %>
    <script type="text/javascript">

        $(function () {
            $("a.deleteClass").click(function () {
                // 在事件的function函数中,有一个this对象。这个this对象
                // 是当前正在响应事件的dom对象
                /**
                 * confirm是确认提示框函数
                 * 参数是它的提示内容
                 * 它有两个按钮,一个确认,应该是取消
                 * 返回true表示点击了,确认,返回false表示点击了取消
                 */
                return confirm("你确定要删除【"+$(this).parent().parent().find("td:first").text()+"】?");

            })
        });

    </script>

</head>
<body>

<div id="header">
    <img class="logo_img" alt="" src="../../static/img/logo.gif">
    <span class="wel_word">图书管理系统</span>
    <%--静态包含manager管理模块的菜单--%>
    <%@ include file="/pages/common/manager_menu.jsp" %>
</div>

<div id="main">
    <table>
        <tr>
            <td>名称</td>
            <td>价格</td>
            <td>作者</td>
            <td>销量</td>
            <td>库存</td>
            <td colspan="2">操作</td>
        </tr>

        <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}">修改</a></td>
                <td><a class="deleteClass" href="manager/bookServlet?action=delete&id=${book.id}">删除</a></td>
            </tr>
        </c:forEach>

        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td><a href="pages/manager/book_edit.jsp">添加图书</a></td>
        </tr>
    </table>

    <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>

<%--静态包含页脚内容--%>
<%@include file="/pages/common/footer.jsp" %>
</body>
</html>

2.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>

        <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>

2.5、分页模块中跳转到指定页数功能实现

    <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 id="searchPageBth" type="button" value="确定">

        <script type="text/javascript">

            $(function () {
                //跳到指定页码
                $("#searchPageBth").click(function () {

                    var pageNo = $("#pn_input").val();

                    //javaScript语言提供了一个location地址栏对象
                    //他有一个属性交href,它可以获取浏览器地址栏中的地址
                    //href 属性可读,可写
                    location.href = "${pageScope.basePath}manager/bookServlet?action=page&pageNo=" + pageNo;
                });
            });
        </script>
    </div>

Page 对象中的修改:

    public void setPageNo(Integer pageNo) {
        //数据边界的有效检查
        if (pageNo < 1) {
            pageNo = 1;
        }

        if (pageNo > pageTotal) {
            pageNo = pageTotal;
        }
        this.pageNo = pageNo;
    }

BookService 中 page 方法的修改:

   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;
    }

2.6、分页模块中,页码 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
<%--页码输出的开始--%>
            <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的情况。假设一共10--%>
                <c:when test="${requestScope.page.pageTotal > 5}">
                    <c:choose>
                        <%--小情况 1:当前页码为前面 3 个:123 的情况,页码范围是: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 个,8910,页码范围是:总页码减 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>
                        <%--小情况 34567,页码范围是:当前页码减 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="manager/bookServlet?action=page&pageNo=${i}">${i}</a>
                </c:if>
            </c:forEach>
            <%--页码输出的结束--%>

2.7、修改分页后,增加,删除,修改图书信息的回显页面

以修改图书为示例:
1、在修改的请求地址上追加当前页码参数:
在这里插入图片描述
2、在 book_edit.jsp 页面中使用隐藏域记录下 pageNo 参数
在这里插入图片描述
3、在服务器重定向的时候,获取当前页码追加上进行跳转

    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"));
    }

3、首页 index.jsp 的跳转

在这里插入图片描述

4、分页条的抽取

4.1、抽取分页条中请求地址为 url 变量

4.1.1.在 page 对象中添加 url 属性

/**
* Page 是分页的模型对象
* @param <T> 是具体的模块的 javaBean 类
    */
    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<T> items;
            // 分页条的请求地址
            private String url;

4.1.2 在 Servlet 程序的 page 分页方法中设置 url 的分页请求地址
在这里插入图片描述
4.1.3、修改分页条中请求地址为 url 变量输出,并抽取一个单独的 jsp 页面

<%--分页条的开始--%>
<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的情况。假设一共10--%>
    <c:when test="${requestScope.page.pageTotal > 5}">
    <c:choose>
        <%--小情况 1:当前页码为前面 3 个:123 的情况,页码范围是: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 个,8910,页码范围是:总页码减 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>
        <%--小情况 34567,页码范围是:当前页码减 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>

<%--页码输出的结束--%>

        <%--如果已经是最后一页,则不显示下一页,末页--%>
        <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="4" name="pn" id="pn_input"/><input id="searchPageBth" type="button" value="确定">

        <script type="text/javascript">

            $(function () {
                //跳到指定页码
                $("#searchPageBth").click(function () {

                    var pageNo = $("#pn_input").val();

                    //javaScript语言提供了一个location地址栏对象
                    //他有一个属性交href,它可以获取浏览器地址栏中的地址
                    //href 属性可读,可写
                    location.href = "${pageScope.basePath}${requestScope.page.url}&pageNo=" + pageNo;
                });
            });
        </script>
</div>
<%--分页条的结束--%>

5、首页价格搜索

在这里插入图片描述
BookServiceImpl中的部分改动:

   @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;
    }

5.1解决的分页条不带价格区间的bug

改动ClientBookServlet类的pageByPrice方法:

    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);

        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);
    }

执行结果:
在这里插入图片描述
翻页过后 页数仍在
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值