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
层的代码如何有效分离,单独工作。
- View 视图:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工合作——JSP/HTML。
- Controller 控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面(转到某个页面或者是重定向到某个页面),是一个“调度者”的角色——Servlet。
- Model 模型:将与业务逻辑相关的数据封装为具体的JavaBean 类,其中不掺杂任何与数据处理相关的代码——JavaBean/domain/entity/pojo。
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
中的代码脚本而存在的。
- 导入
JSTL
的jar
包taglibs-standard-impl-1.2.1.jar
taglibs-standard-spec-1.2.1.jar
- 在
book_manager.jsp
开头加上:
*<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- 利用
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>
- 因为此时的表单上传是
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)
处理流程:
- 客户端发送请求,Servlet做出业务逻辑处理;
- Servlet调用forword()方法,服务器Servlet把目标资源返回给客户端浏览器。
2)重定向
response.sendRedirect(URL地址)
处理流程:
- 客户端发送请求,Servlet做出业务逻辑处理;
- Servlet调用response.sendReadirect()方法,把要访问的目标资源作为response响应头信息发给客户端浏览器;
- 客户端浏览器重新访问服务器资源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 演示
自己录制的视频演示:
书城项目第四阶段
代码就是这么神奇,同样的程序,今天出现了问题,结果第二天无缘无故又可以实现了,所以说,遇到解决不了的Bug时,先放一放,待会再调试。
标签:Java,Book,void,id,第四阶段,book,图书,public,书城 来源: https://blog.csdn.net/weixin_44262126/article/details/113415551