【JavaWeb 实际项目 04】

第五部分:图书模块

主要包含:首页的图书管理,后台管理-图书管理

一、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>        
原文地址:https://www.cnblogs.com/frankruby/p/15012425.html