第五部分:图书模块
主要包含:首页的图书管理,后台管理-图书管理
一、MVC概念
MVC全称:Model模型,View视图,Controller控制器
MVC最早出现在JavaEE三层中的web层,它可以知道代码有效的分隔,单独工作
view视图:只负责数据和界面的显示,不接受任何与数据无关的代码,便于程序员和美工到的分工合作--JSP/HTML
controller控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个调度者的角色--Servlet转到某个页面。或者是重定向到某个页面
Model模型:将与业务逻辑相关的数据封装为具体的JavaBean类,其中不掺杂任何与数据处理相关的代码--javaBean/domain/entity/pojo
MVC是一种思想
MVC的理念是将软件代码拆分为组件,单独开发,组合使用(目的还是为了降低耦合度)
mvc的作用还是为了降低耦合。让代码合理分层。方便后期升级和维护
二、图书模块
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;
2、编写图书模块的JavaBean
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"; //图片路径这个需要有个判断 -->在构造方法内编写下面的代码 //要求给定图书封面图书路径不能为空 if(imgPath != null||"".equals(imgPath)){ this.imgPath = imgPath; }
3、编写图书模块的dao和测试dao
BookDao接口 -->查看页面发现,图书模块也是包含了增删改查的操作,所以写增删改查的方法
public interface BookDao { //查看页面发现,图书模块也是包含了增删改查的操作 public int addBook(Book book); public int deleteBook(Integer id); public int updateBook(Book book); public Book queryBookById(Integer id); public List<Book> queryBooks(); }
BookDaoImpl类
package com.wufq.dao.impl; import com.wufq.dao.BookDao; import com.wufq.pojo.Book; import java.util.List; /** * @Description * @Author wufq * @Version * @Date 2021/7/19 11:30 */ 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` imgPath from t_book where id=?"; return queryForOne(sql,Book.class,id); } @Override public List<Book> queryBooks() { String sql="select `id`,`name`,`author`,`price`,`sales`,`stock`,`img_path` imgPath from t_book"; return queryForList(sql,Book.class); } }
BookDaoTest测试类
package com.wufq.test; import com.wufq.dao.BookDao; import com.wufq.dao.impl.BookDaoImpl; import com.wufq.pojo.Book; import org.junit.Test; import java.math.BigDecimal; /** * @Description * @Author wufq * @Version * @Date 2021/7/23 15:18 */ public class BookDaoTest { private BookDao bookDao = new BookDaoImpl(); @Test public void addBook() throws Exception { bookDao.addBook(new Book(null,"尘封好厉害","wufq",new BigDecimal(9999),110000,0,null)); } @Test public void deleteBook() throws Exception { bookDao.deleteBook(20); } @Test public void updateBook() throws Exception { bookDao.updateBook(new Book(19,"大家都好厉害","wufq",new BigDecimal(9999),1100000,0,null)); } @Test public void queryBookById() throws Exception { System.out.println(bookDao.queryBookById(10)); } @Test public void queryBooks() throws Exception { for(Book querybook : bookDao.queryBooks()) { System.out.println(querybook); } } }
4、编写图书模块的Service和测试Service
BookService接口
package com.wufq.service; import com.wufq.pojo.Book; import java.util.List; /** * @Description * @Author wufq * @Version * @Date 2021/7/23 17:14 */ 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类
package com.wufq.service.impl; import com.wufq.dao.BookDao; import com.wufq.dao.impl.BookDaoImpl; import com.wufq.pojo.Book; import com.wufq.service.BookService; import java.util.List; /** * @Description * @Author wufq * @Version * @Date 2021/7/23 17:20 */ public class BookServiceImpl implements BookService{ private BookDao bookDao= new BookDaoImpl(); @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); } @Override public List<Book> queryBooks() { return bookDao.queryBooks(); } }
5、编写图书模块的Web层,和页面联调测试
5.1、图书列表功能的实现
|-- 列表功能的流程
1、修改图书管理的请求地址(manager.jsp) -->依据上面的流程,manager.jsp通过BookServlet程序请求到图书信息的页面数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <div><a href="manager/bookServlet?action=list">图书管理</a> <a href="pages/manager/order_manager.jsp">订单管理</a> <a href="index.jsp">返回商城</a> </div>
manager/bookServlet?请求资源地址,action=list服务器请求的那个方法
2、编写BookServlet的list请求
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 -->这里面的第一个/指的是web目录 req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req, resp); }
3、修改/pages/manager/book_manager.jsp页面的数据遍历输出
|-- 首先我们要导入JSTL的包
<%--循环遍历域中的数据,${requestScope.books}中的books是BookServlet里面的全部图书存储的域名--%> <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>
web.xml文件内配置BookServlet
<servlet-mapping> <servlet-name>BookServlet</servlet-name> <!--加manager不是manager这个目录,只是为了后面权限的管理方便--> <url-pattern>/manager/bookServlet</url-pattern> </servlet-mapping>
为什么要前面加manager呢?
通过前后台简单介绍来理解为什么需要加?
其实就是为了区分前后台访问时的权限问题。
5.2、添加图书功能实现
添加图书的流程:
1、修改book_edit.jsp请求BookServlet的地址
<body> <div id="header"> <img class="logo_img" alt="" src="static/img/client-7.png" > <span class="wel_word">编辑图书</span> <%--manager静态模块--%> <%@include file="/pages/common/manager.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> <%--这里要把前面的book去掉,因为要和book的bean里面的属性保持一致--%> <%--<td><input name="book_name" type="text" value="时间简史"/></td>--%> <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/fooler.jsp"%> </body>
2、编写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 /* * 这么写有一个bug:重复提交表单,当用户在页面刷新(F5)时,会发送两次请求并且请求的地址是最后一次请求的地址 * (http://localhost:8080/book/manager/bookServlet?action=add&name=xxx&price=30.00&author=xxx&sales=200&stock=300) * * 解决这种问题,需要加上一个重定向:重新把去请求的地址跳转到提交之前的地址上 * (http://localhost:8080/book/manager/bookServlet?action=list) */ //req.getRequestDispatcher("/manager/bookServlet?action=list").forward(req, resp); resp.sendRedirect(req.getContextPath()+"/manager/bookServlet?action=list"); }
5.3、删除图书功能的实现
1、删除流程
点击删除按钮(删除按钮对应发送到服务器的地址:manager/bookServlet?action=delete&id=图书编号),请求到BookServlet处理后返回地址到浏览器
2、修改book_manager.jsp文件
<%--循环遍历域中的数据,${requestScope.books}中的books是BookServlet里面的全部图书存储的域名--%> <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="/manager/bookServlet?action=delete&${book.id}">删除</a></td> </tr> </c:forEach>
注意:book.id是页面传过来的id,而id,name...等又是通过BookDaoImpl对应的sql语句中查询出来的
3、bookServlet编写delete方法
protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、获取请求的参数id,图书编号 int id = WebUtils.parseInter(req.getParameter("id"),0); //2、调用BookService.deleteBookById(),删除图书 bookService.deleteBookById(id); //3、重定向回图书列表管理页面 resp.sendRedirect(req.getContextPath()+"/manager/bookServlet?action=list"); }
4、WebUtils内添加int类型转换的工具方法
// String类型转换成Integer类型 public static int parseInter(String str,int defautInt){ try { return Integer.parseInt(str); } catch (NumberFormatException e) { e.printStackTrace(); } return defautInt; }
5、在book_manager.jsp中给删除添加确认提示操作
<head> <meta charset="UTF-8"> <title>图书管理</title> <%--静态包含base标签、css样式、jQuery--%> <%@include file="/pages/common/head.jsp"%> <%--给删除添加删除确认操作--%> <script type="text/javascript"> $(function(){ //给删除的a标签绑定单击事件,用于删除的确认操作 $("a.deleteClass").click(function(){ /*在时间的function函数中,有一个this对象,这个this对象,是当前正在响应的dom对象 confirm 是确认提示框函数 参数是他的提示内容 他有两个按钮,一个确认按钮,一个取消按钮 返回true表示点击,返回false表示取消了 $(this)-->表示删除的a标签对象,parent是获取他的父层td,tr.find("td:first").text()-->表示去找td下面的第一个内容文本 * */ return confirm("你确定要删除【"+$(this).parent().parent().find("td:first").text()+"】") }); }); </script> </head>
5.4、修改图书功能的实现
1、修改流程
2、修改book_manager.jsp内【修改】的请求地址
<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>
3、增加BookServlet内getBook方法
protected void getBook(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //1、获取图书编号 int id = WebUtils.parseInter(req.getParameter("id"),0); //2、调用bookService.queryBookById(id)得到图书信息 Book book = bookService.queryBookById(id); //3、把图书信息保存到图书域中 req.setAttribute("book",book); //4、请求转发到book_edit.jsp页面 req.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(req,resp); }
4、修改book_edit.jsp页面
<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>
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"); }
6、解决book_edit.jsp页面,既要实现添加操作,又要实现修改操作
<div id="main"> <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}"/> <table> <tr> <td>名称</td> <td>价格</td> <td>作者</td> <td>销量</td> <td>库存</td> <td colspan="2">操作</td> </tr>