编程语言
首页 > 编程语言> > Java书城项目第四阶段:图书模块

Java书城项目第四阶段:图书模块

作者:互联网

1)本项目根据JavaWeb的学习过程分为几个部分,分别是表单验证、用户注册与登录、修改所有HTML页面为JSP页面……其中每一部分都对应JavaWeb的一些技术栈,由浅入深,从而对JavaWeb有一个整体的把握。
2)该项目所需要用到的技术有Java、MySQL、HTML、CSS、JavaScript、JQuery、XML、Tomcat、Servlet等,需要有相应基础的同学才能更好的学习该部分内容。想了解这些技术,可查看我的其它文章,下面为链接:
Servlet:Servlet必知必会
        在慢慢增加了,等等哈
3)代码的具体实现可以参考代码中的注释,如果由于注释不清楚而不明白相应原理,可以与作者私聊,欢迎互相交流。

目录索引

1 需求

这一阶段的内容是第二阶段用户登录模块的拓展,进一步学习了项目中最常用的遍历、增、删、改、查

1.1 具体需求

需要的界面如下图所示,通过点击页面上的修改、删除或者添加图书,可以实现我们功能。
在这里插入图片描述 

2 数据库

2.1 创建图书模块所需要的数据库表

#下面就是为了创建图书模块的数据库
create table book(
                       `id` int primary key auto_increment,
                       `name` varchar(100),
                       `price` decimal(11,2),
                       `author` varchar(100),
                       `sales` int,
                       `stock` int,
                       `img_path` varchar(200)
);

## 插入初始化测试数据
insert into book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
values(null , 'java从入门到放弃' , 'sharm' , 80 , 9999 , 9 , 'static/img/default.jpg');

insert into book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
values(null , '数据结构与算法' , 'sharm' , 78.5 , 6 , 13 , 'static/img/default.jpg');

insert into book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
values(null , 'Java编程思想' , 'sharm' , 99.5 , 47 , 36 , 'static/img/default.jpg');

insert into book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
values(null , '操作系统原理' , 'sharm' , 133.05 , 122 , 188 , 'static/img/default.jpg');

insert into book(`id` , `name` , `author` , `price` , `sales` , `stock` , `img_path`)
values(null , '大话设计模式' , 'sharm' , 89.15 , 20 , 10 , 'static/img/default.jpg');

## 查看表内容
select id,name,author,price,sales,stock,img_path from book;

2.2 创建表对应的JavaBean对象

pojo包下新建Book.java作为上表所对应的JavaBean对象。

import java.math.BigDecimal;

public class Book {
    //1 首先是定义变量
    //Integer可以为null,而int不能为null
    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";

    //2 接下来是无参构造函数
    public Book(){
    }
    //3 接下来是有参构造函数
    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;
        }
    }

    //4 然后是getter与setter方法
    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) {
        // 要求给定的图书封面图书路径不能为空
        if (imgPath != null && !"".equals(imgPath)) {
            this.imgPath = imgPath;
        }
    }
    //5 最后是重写同toString方法
    @Override
    public String toString() {
        return "Book{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", sales=" + sales +
                ", stock=" + stock +
                ", imgPath='" + imgPath + '\'' +
                '}';
    }
}

 

3 编写Dao持久层

BaseDao这一父类的基础上通过实现BookDao接口所约束的方法来进行BookDaoImp类的编写。

3.1 编写BookDao接口

import sharm.pojo.Book;

import java.util.List;

/**
 * 这个接口约束了图书管理中的遍历、增、删、改功能
 */
public interface BookDao {
    public List<Book> queryBooks();

    public int addBook(Book book);

    public int deleteBookById(Integer id);

    public int updateBook(Book book);

    public Book queryBookById(Integer id);
}

3.2 编写BookDaoImp实现类

import sharm.dao.BookDao;
import sharm.pojo.Book;

import java.util.List;

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

    @Override
    public int addBook(Book book) {
        String sql = "insert into 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 book where id = ?";
        return update(sql, id);
    }

    @Override
    public int updateBook(Book book) {
        String sql = "update 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` imgPath from book where id = ?";
        return queryForOne(Book.class, sql, id);
    }
}

3.3 编写BookDaoImpTest测试类

IDEA中,在对应的接口上点击ctrl+shift+t,可以直接生成测试类。

import sharm.dao.BookDao;
import sharm.dao.impl.BookDaoImp;
import sharm.pojo.Book;

import java.math.BigDecimal;

import static org.junit.Assert.*;

public class BookDaoTest {
    //多态 左边是接口,右边是实现类
    private BookDao bookDao = new BookDaoImp();

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

    @Test
    public void addBook() {
        bookDao.addBook(new Book(null,"坚持", "sharm", new BigDecimal(13),13,0,null));
    }

    @Test
    public void deleteBookById() {
        bookDao.deleteBookById(3);
    }

    @Test
    public void updateBook() {
        bookDao.updateBook(new Book(4,"人生", "sharm", new BigDecimal(9999),1100000,0,null));
    }

    @Test
    public void queryBookById() {
        System.out.println( bookDao.queryBookById(4));
    }
}

 

4 编写Service服务层

4.1 编写BookService接口

import sharm.pojo.Book;

import java.util.List;

/**
 * 此时Service的业务层的具体业务刚好与Dao层相同
 */
public interface BookService {

    public List<Book> queryBooks();

    public void addBook(Book book);

    public void deleteBookById(Integer id);

    public void updateBook(Book book);

    public Book queryBookById(Integer id);
}

4.2 编写BookServiceImp实现类

import sharm.dao.BookDao;
import sharm.dao.impl.BookDaoImp;
import sharm.pojo.Book;
import sharm.service.BookService;

import java.util.List;

public class BookServiceImp implements BookService {
    //依旧多态
    private BookDao bookdao=new BookDaoImp();
    @Override
    public List<Book> queryBooks() {
        return  bookdao.queryBooks();
    }

    @Override
    public void addBook(Book book) {
        bookdao.addBook(book);
    }

    @Override
    public void deleteBookById(Integer id) {
        bookdao.deleteBookById(id);
    }

    @Override
    public void updateBook(Book book) {
    bookdao.updateBook(book);
    }

    @Override
    public Book queryBookById(Integer id) {
        return bookdao.queryBookById(id);
    }
}

4.3 编写BookServiceImpTest测试类

import sharm.pojo.Book;
import sharm.service.BookService;
import sharm.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 addBook() {
        bookService.addBook(new Book(null,"人生", "1125", new BigDecimal(1000000), 100000000, 0, null));
    }

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

    @Test
    public void updateBook() {
        bookService.updateBook(new Book(2,"生活", "1125", new BigDecimal(999999), 10, 111110, null));
    }

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

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

 

5 编写Web层

5.1 MVC概念

MVC 全称为Model 模型、View 视图、Controller 控制器。MVC 最早出现在JavaEE 三层中的Web 层,它可以有效的指导Web 层的代码如何有效分离,单独工作。

MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了降低耦合度)。在这里插入图片描述

5.2 遍历图书功能的实现

5.2.1 需求

当我们点击主页上的后台管理-图书管理时,网页上需要出现目前书城所有书的列表。

5.2.2 思路

当点击图书管理时,我们不能直接将其链接到展示列表网页的manager.jsp中,因为该jsp是没有图书信息的,图书信息在我们的后端数据库中,正确的方法应该是当点击图书管理时,将其链接到Web层的BookServlet程序中,让Web层从数据库中拿到数据,然后将数据保存到Request域中,并将其转发到展示列表网页的manager.jsp。完整步骤如下所示:
在这里插入图片描述

介绍一下实际工程中的前台与后台。
在这里插入图片描述

5.2.3 代码实现

1)在web层新建BookServlet,同时在web.xml加入前端与后台Servlet程序的映射文件

    <servlet>
        <servlet-name>BookServlet</servlet-name>
        <servlet-class>sharm.web.BookServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>BookServlet</servlet-name>
        <!--这里介绍一下前后端的区别-->
        <url-pattern>/manager/bookServlet</url-pattern>
    </servlet-mapping>

2)修改【图书管理】请求地址

打开common包的manager_menu.jsp文件,修改图书管理的href为:

<%--?action=list表示打开BookServlet中的list方法--%>
<a href="manager/bookServlet?action=list">图书管理</a>

3)在BookServlet里写上遍历的代码

    private BookService bookService = new BookServiceImp();
    protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1 通过BookService查询全部图书
        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);
    }

4)利用JSTL表达式修改pages/manager/book_manager.jsp 页面的数据遍历输出。众所周知,JSTL是为了替换jsp中的代码脚本而存在的。

  1. 导入JSTLjar
    • taglibs-standard-impl-1.2.1.jar
    • taglibs-standard-spec-1.2.1.jar
  2. book_manager.jsp开头加上:
*<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  1. 利用JSTL表达式修改原来的遍历函数
			<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="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>
  1. 因为此时的表单上传是doGet请求,而之前在BaseServlet中只弄好了doPost请求,所以需要……在doGet请求里面调用doPost方法。
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

在实际的代码书写中,不同的编程环境肯定会遇到很多的Bug,所以一定要学会解决Bug。

5.3 添加图书功能的实现

5.3.1 需求

系统会按照自己上传的图书信息(包括书名、作者等)达到添加图书的功能,同时,当添加完成后会自动刷新数据,显示添加的图书。

5.3.2 思路

实现思路图如下所示:
在这里插入图片描述

5.3.3 请求转发与重定向

1)请求转发

request.getRequestDispatcher(URL地址).forward(request, response)

处理流程:

  1. 客户端发送请求,Servlet做出业务逻辑处理;
  2. Servlet调用forword()方法,服务器Servlet把目标资源返回给客户端浏览器。

2)重定向

response.sendRedirect(URL地址)

处理流程:

  1. 客户端发送请求,Servlet做出业务逻辑处理;
  2. Servlet调用response.sendReadirect()方法,把要访问的目标资源作为response响应头信息发给客户端浏览器;
  3. 客户端浏览器重新访问服务器资源xxx.jsp,服务器再次对客户端浏览器做出响应。

5.3.4 代码实现

1)BookServlet程序中添加add方法

    private BookService bookService = new BookServiceImp();

    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 跳到图书列表页面
        //利用重定向而非请求转发来达到跳到图书列表页面的目的
        //req.getRequestDispatcher("/manager/bookServlet?action=list").forward(req, resp);
        resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");
    }

2)修改book_edit.jsp 页面

<form action="manager/bookServlet" method="get">
<input type="hidden" name="action" value="add" />

5.4 删除图书功能的实现

5.4.1 需求

可以根据自己点击删除某一本图书,同时在删除时给用户一个确认删除的界面,防止用户误删除。

5.4.2 思路

实现思路图如下所示:
在这里插入图片描述

5.4.3 代码实现

1)在BookServlet 程序中添加delete 方法

	private BookService bookService = new BookServiceImp();
    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 重定向回图书列表管理页面
        resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");
    }

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

3)加入单击事件来防止用户误删除

<title>图书管理</title>
	<%--静态包含头内容--%>
	<%--加入单击事件来防止用户误删除--%>
	<%@include file="/pages/common/head.jsp"%>
	<script type="text/javascript">
		$(function () {
			// 给删除的a标签绑定单击事件,用于删除的确认提示操作
			$("a.deleteClass").click(function () {
				// 在事件的function函数中,有一个this对象。这个this对象,是当前正在响应事件的dom对象。
				/**
				 * confirm是确认提示框函数
				 * 参数是它的提示内容
				 * 它有两个按钮,一个确认,一个是取消。
				 * 返回true表示点击了,确认,返回false表示点击取消。
				 */
				return confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() + "】?");
				// return false// 阻止元素的默认行为===不提交请求
			});
		});
	</script>

5.5 修改图书功能的实现

5.5.1 需求

修改书城中图书的具体信息。

5.5.2 思路

实现思路图如下所示:
在这里插入图片描述

5.5.3 代码实现

1)更新【修改】的请求地址

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

2)在BookServlet 程序中添加getBook 方法

	private BookService bookService = new BookServiceImp();
    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);
    }

3)在BookServlet 程序中添加update 方法

	private BookService bookService = new BookServiceImp();
    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 重定向回图书列表管理页面
        resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=list");
    }

4)解决book_edit.jsp 页面,即要实现添加,又要实现修改操作

<form action="manager/bookServlet" method="get">
<input type="hidden" name="action" value="${ empty param.id ? "add" : "update" }" />
<input type="hidden" name="id" value="${ requestScope.book.id }" />

 

6 演示

自己录制的视频演示:

<iframe allowfullscreen="true" data-mediaembed="bilibili" id="IvzOiLLp-1611983880597" src="https://player.bilibili.com/player.html?aid=288888038"></iframe>

书城项目第四阶段

代码就是这么神奇,同样的程序,今天出现了问题,结果第二天无缘无故又可以实现了,所以说,遇到解决不了的Bug时,先放一放,待会再调试。

标签:Java,Book,void,id,第四阶段,book,图书,public,书城
来源: https://blog.csdn.net/weixin_44262126/article/details/113415551