day09 书城项目第三阶段

day09 书城项目第三阶段

1. 项目准备工作

1.1 创建Module

在这里插入图片描述

1.2 拷贝jar包

  1. 数据库jar包
  2. Thymeleaf的jar包
    在这里插入图片描述

1.3 从V2版本项目迁移代码

1.3.1 迁移src目录下的Java源代码

在这里插入图片描述

  • 拷贝resources目录,然后将resource目录标记成Resources Root
  • 拷贝src目录下的内容,并且将原有的Servlet全部删除
  • 创建两个子包
    • 存放Servlet基类:com.atguigu.bookstore.servlet.base
    • 存放Servlet子类:com.atguigu.bookstore.servlet.app
  • 从资料中将两个基类拷贝过来,放置到com.atguigu.bookstore.servlet.base包里面
    • 视图基类:ViewBaseServlet
    • 方法分发基类:BaseServlet
1.3.2 迁移前端代码
  • 将V02中的pages目录整体复制到V03 module的WEB-INF目录下
  • 将V02中的static目录整体复制到V03 module的web目录下
  • 将V02中的index.html复制到V03 module的WEB-INF/pages目录下,将来通过Servlet访问

1.4 显示首页

1.4.1 修改web.xml
<!-- 在上下文参数中配置视图前缀和视图后缀 -->
<context-param>
    <param-name>start</param-name>
    <param-value>/WEB-INF/pages/</param-value>
</context-param>
<context-param>
    <param-name>end</param-name>
    <param-value>.html</param-value>
</context-param>

注意:这里需要将WEB-INF下的view改成pages,和当前项目环境的目录结构一致。

1.4.2 创建IndexServlet

注意:这个IndexServlet映射的地址是/index.html,这样才能保证访问首页时访问它。

注意:IndexServlet服务于首页的显示,为了降低用户访问首页的门槛,不能附加任何请求参数,所以不能继承ModelBaseServlet,只能继承ViewBaseServlet。

package com.atguigu.servlet.app;

import com.atguigu.servlet.base.ViewBaseServlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/index.html")
public class IndexServlet extends ViewBaseServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processTemplate("index", req, resp);
    }
}

1.4.3 调整index.html
  • 加入Thymeleaf名称空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  • 修改base标签
<base th:href="@{/}">

2. 完成用户模块

2.1 重构登录功能

2.1.1 思路

在这里插入图片描述

2.1.2 代码
① 创建UserServlet

Java代码:

package com.atguigu.servlet.app;

import com.atguigu.pojo.User;
import com.atguigu.service.UserService;
import com.atguigu.service.impl.UserServiceImpl;
import com.atguigu.servlet.base.ModelBaseServlet;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet("/user")
public class UserServlet extends ModelBaseServlet {
    // 创建业务层对象
    UserService service = new UserServiceImpl();
    // 去登陆页面
    protected void toLoginPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processTemplate("user/login", req, resp);
    }
}

注意:记得修改UserServlet继承的类ModelBaseServlet

② 前往登录页面功能

a. 修改首页中登录超链接

<a href="user?method=toLoginPage" class="login">登录</a>

b. 完成UserServlet.toLoginPage()方法

// 去登陆页面
protected void toLoginPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    processTemplate("user/login", req, resp);
}

c. 调整登录页面代码

  • 加入Thymeleaf名称空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  • 修改base标签
<base th:href="@{/}"  />
  • 修改form标签action属性
<form action="user">
  • 增加method请求参数的表单隐藏域
<input type="hidden" name="method" value="login">
  • 根据条件显示登录失败消息
<span class="errorMsg">{{errMessage}}</span>
③ 登录校验功能

a. UserServlet.Login()

// 登录逻辑
protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 获取请求参数
    Map<String, String[]> map = req.getParameterMap();
    String check = req.getParameter("check");
    // 将请求参数封装到User对象中
    User user = new User();
    try {
        BeanUtils.populate(user, map);
        UserService userService = new UserServiceImpl();
        // 调用业务层的方法处理登录
        userService.doLogin(user);
        // 调用toLoginSuccessPage方法
        resp.sendRedirect(req.getContextPath() + "/user?method=toLoginSuccessPage");
    } catch (Exception e) {
        e.printStackTrace();
        // 出现异常 返回异常信息
        req.setAttribute("eMsg", e.getMessage());
        // 跳转到登录页面
        processTemplate("user/login", req, resp);
    }
}
// 去往登录成功页面
protected void toLoginSuccessPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    setCookie(req, resp);
    processTemplate("user/login_success", req, resp);
}

b. 回显表单中的用户名

在login.html页面进行设置

遇到问题:使用th:value="${param.username}"确实实现了服务器端渲染,但是实际打开页面并没有看到。原因是页面渲染顺序:

  • 服务器端渲染
  • 服务器端将渲染结果作为响应数据返回给浏览器
  • 浏览器加载HTML文档
  • 读取到Vue代码后,执行Vue代码
  • Vue又进行了一次浏览器端渲染,覆盖了服务器端渲染的值

解决办法:将服务器端渲染的结果设置到Vue对象的data属性中。

new Vue({
    "el": "#box",
    "data":{
        "errMessage": "[[${errmsg} == null ? '请输入用户名和密码' : ${errmsg}]]",
        "username":"[[${param.username}]]",
        "password":""
    },

c. 修改login_success.html页面

login_success.html

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
	<base th:href="@{/}">

2.2 重构注册功能

2.2.1 思路

在这里插入图片描述

2.2.2 代码
① 前往注册页面功能

a. 修改首页中注册超链接

<a href="user?method=toRegistPage" class="register">注册</a>

b. 完成UserServlet.toRegistPage()方法

    // 去往注册页面
    protected void toRegistPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        processTemplate("user/regist", req, resp);
    }

c 调整注册页面代码

<html lang="en" xmlns:th="http://www.thymeleaf.org">
    ……
<base th:href="@{/}" href="/bookstore/"/>
    ……
    
	<form action="user">
          <input type="hidden" name="method" value="regist">
        ……
//注册失败后回显数据(用户名和邮箱)
    new Vue({
      "el": "#box",
      "data":{
        // 用户名信息
        "username":"[[${param.username}]]",
        "usernameErrMsg":"用户名应为3~16位数字和字母组成",
        "usernameCss":{
              "visibility":"hidden"
        },
        // 密码信息
        "password":"",
        "passwordErrMsg":"密码的长度至少为5位",
        "passwordCss":{
              "visibility":"hidden"
        },
        // 确认密码信息
        "dbpassword":"",
        "dbpasswordErrMsg":"密码两次输入不一致",
        "dbpasswordCss":{
              "visibility":"hidden"
        },
        // 邮箱信息
        "email":"[[${param.email}]]",
        "emailErrMsg":"请输入正确的邮箱格式",
        "emailCss":{
              "visibility":"hidden"
        }
      },
② 注册功能

UserServlet代码

    // 注册逻辑
    protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取所有的请求参数
        Map<String, String[]> parameterMap = req.getParameterMap();
        // 将parameterMap中的数据封装到User对象中
        User user = new User();
        try {
            BeanUtils.populate(user, parameterMap);
            // 创建业务层的对象
            UserService userService = new UserServiceImpl();
            // 调用业务层的方法 如果注册失败了 业务层会抛出异常
            userService.doRegister(user);
            // 调用toRegistSuccessPage方法
            resp.sendRedirect(req.getContextPath() + "/user?method=toRegistSuccessPage");
        } catch (Exception e) {
            e.printStackTrace();
            // 如果出现异常 那就是注册失败
            req.setAttribute("errMsg", e.getMessage());
            // 跳转到注册页面
            processTemplate("user/regist", req, resp);

        }
    }
    // 去往注册成功页面
    protected void toRegistSuccessPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 请求转发跳转到注册成功页面
        processTemplate("user/regist_success", req, resp);
    }

b. 修改regist_success.html页面

<html xmlns:th="http://www.thymeleaf.org">
<head>
	<base th:href="@{/}">

3. 书城后台CRUD

3.1 进入后台页面

3.1.1 概念辨析

在这里插入图片描述

3.1.2 访问后台首页
① 思路

首页→后台系统超链接→AdminServlet.toManagerPage()→manager.html

② 代码
a. 创建AdminServlet

Java代码:

package com.atguigu.servlet.app;

import com.atguigu.servlet.base.ModelBaseServlet;
import com.atguigu.servlet.base.ViewBaseServlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/admin")
public class AdminServlet extends ViewBaseServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processTemplate("manager/manager", req, resp);
    }
}

b. 调整manager.html
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<base th:href="@{/}">

然后去除页面上的所有“…/”

c. 抽取页面公共部分
  1. 创建包含代码片段的页面
    在这里插入图片描述

fragment/menu.html的代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>menu</title>
</head>
<body>
<div th:fragment="commentmenu">
    <a href="book?method=getAll">图书管理</a>
    <a href="order_manager.html">订单管理</a>
    <a href="index.html">返回商城</a>
</div>

</body>
</html>
  1. 在有需要的页面(book_edit.html、book_manager.html、order_manager.html)引入片段
    <div class="header-right"  th:include="fragment/menu::commentmenu" >

3.2 后台图书CRUD

3.2.1 数据建模
① 物理建模
CREATE TABLE books(
	id INT PRIMARY KEY AUTO_INCREMENT,
	title VARCHAR(200),
	author VARCHAR(200),
	price DOUBLE,
	sales INT,
	stock INT,
	img_path VARCHAR(100)
);
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('解忧杂货店','东野圭吾',27.20,100,100,'static/uploads/jieyouzahuodian.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('边城','沈从文',23.00,100,100,'static/uploads/biancheng.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('中国哲学史','冯友兰',44.5,100,100,'static/uploads/zhongguozhexueshi.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('忽然七日',' 劳伦',19.33,100,100,'static/uploads/huranqiri.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('苏东坡传','林语堂',19.30,100,100,'static/uploads/sudongpozhuan.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('百年孤独','马尔克斯',29.50,100,100,'static/uploads/bainiangudu.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('扶桑','严歌苓',19.8,100,100,'static/uploads/fusang.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('给孩子的诗','北岛',22.20,100,100,'static/uploads/geihaizideshi.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('为奴十二年','所罗门',16.5,100,100,'static/uploads/weinushiernian.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('平凡的世界','路遥',55.00,100,100,'static/uploads/pingfandeshijie.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('悟空传','今何在',14.00,100,100,'static/uploads/wukongzhuan.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('硬派健身','斌卡',31.20,100,100,'static/uploads/yingpaijianshen.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('从晚清到民国','唐德刚',39.90,100,100,'static/uploads/congwanqingdaominguo.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('三体','刘慈欣',56.5,100,100,'static/uploads/santi.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('看见','柴静',19.50,100,100,'static/uploads/kanjian.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('活着','余华',11.00,100,100,'static/uploads/huozhe.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('小王子','安托万',19.20,100,100,'static/uploads/xiaowangzi.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('我们仨','杨绛',11.30,100,100,'static/uploads/womensa.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('生命不息,折腾不止','罗永浩',25.20,100,100,'static/uploads/shengmingbuxi.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('皮囊','蔡崇达',23.90,100,100,'static/uploads/pinang.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('恰到好处的幸福','毕淑敏',16.40,100,100,'static/uploads/qiadaohaochudexingfu.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('大数据预测','埃里克',37.20,100,100,'static/uploads/dashujuyuce.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('人月神话','布鲁克斯',55.90,100,100,'static/uploads/renyueshenhua.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('C语言入门经典','霍尔顿',45.00,100,100,'static/uploads/cyuyanrumenjingdian.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('数学之美','吴军',29.90,100,100,'static/uploads/shuxuezhimei.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('Java编程思想','埃史尔',70.50,100,100,'static/uploads/Javabianchengsixiang.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('设计模式之禅','秦小波',20.20,100,100,'static/uploads/shejimoshizhichan.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('图解机器学习','杉山将',33.80,100,100,'static/uploads/tujiejiqixuexi.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('艾伦图灵传','安德鲁',47.20,100,100,'static/uploads/ailuntulingzhuan.jpg');
INSERT INTO books (title, author ,price, sales , stock , img_path) VALUES('教父','马里奥普佐',29.00,100,100,'static/uploads/jiaofu.jpg');
② 逻辑建模
package com.atguigu.pojo;

public class Book {
    private Integer id;
    private String title;
    private String author;
    private Double price;
    private Integer sales;
    private Integer stock;
    private String imgPath;

    public Book() {
    }

    public Book(Integer id, String title, String author, Double price, Integer sales, Integer stock, String imgPath) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.price = price;
        this.sales = sales;
        this.stock = stock;
        this.imgPath = imgPath;
    }

    public Integer getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

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

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double 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 +
                ", title='" + title + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", sales=" + sales +
                ", stock=" + stock +
                ", imgPath='" + imgPath + '\'' +
                '}';
    }
}

3.2.2 创建并组装组件
① 创建Servlet
  • 后台:BookServlet
② 创建BookService
  • 接口:BookService
  • 实现类:BookServiceImpl
③ 创建BookDao
  • 接口:BookDao
  • 实现类:BookDaoImpl
④ 组装
  • 给BookServlet组装BookService
  • 给BookService组装BookDao
3.2.3 图书列表显示功能
① 思路

manager.html→图书管理超链接→BookServlet→toBookManagerPage()→book_manager.html

② 修改图书管理超链接

超链接所在文件位置:

WEB-INF/pages/fragment/menu.html

<a href="book?method=getAll">图书管理</a>
③ BookServlet.getAll()
package com.atguigu.servlet.app;

import com.atguigu.pojo.Book;
import com.atguigu.service.BookService;
import com.atguigu.service.impl.BookServiceImpl;
import com.atguigu.servlet.base.ModelBaseServlet;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;

@WebServlet("/book")
public class BookServlet extends ModelBaseServlet {
    // 创建业务层对象
    BookService service = new BookServiceImpl();    
	// 获取所有图书
    protected void getAll(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        List<Book> all = service.getAll();
        req.setAttribute("books", all);
        processTemplate("manager/book_manager", req, resp);
    }
}
④ BookService.getAll()
package com.atguigu.service.impl;

import com.atguigu.dao.BaseDao;
import com.atguigu.dao.BookDao;
import com.atguigu.dao.impl.BookDaoImpl;
import com.atguigu.pojo.Book;
import com.atguigu.service.BookService;

import java.util.List;

public class BookServiceImpl implements BookService {

    BookDao dao = new BookDaoImpl();
    @Override
    public List<Book> getAll() {
        List<Book> books = dao.selectAll();
        return books;
    }
}
⑤ BookDao.selectAll()
package com.atguigu.dao.impl;

import com.atguigu.dao.BaseDao;
import com.atguigu.dao.BookDao;
import com.atguigu.pojo.Book;

import java.util.List;

public class BookDaoImpl extends BaseDao implements BookDao {
    @Override
    public List<Book> selectAll() {
        String sql = "SELECT id,title,author,price,sales,stock,img_path imgPath FROM books;";
        List<Book> books = findAllBean(sql, Book.class);
        return books;
    }
}
⑥ 调整book_manager.html
  • Thymeleaf名称空间: xmlns:th="http://www.thymeleaf.org"
  • base标签: <base th:href="@{/}">
  • 替换页面路径中的../../../
  • 包含进来的代码片段: <div class="header-right" th:include="fragment/menu::commentmenu" >
⑦ 在book_manager.html中迭代显示图书列表
<table>
    <thead>
        <tr>
            <th>图片</th>
            <th>商品名称</th>
            <th>价格</th>
            <th>作者</th>
            <th>销量</th>
            <th>库存</th>
            <th>操作</th>
        </tr>
      </thead>
      <tbody>
      <tr th:each="b  : ${books}">
        <td>
          <img th:src="${b.imgPath}" alt="" />
        </td>
        <td th:text="${b.title}"></td>
        <td th:text="${b.price}">
          100.00
        </td>
        <td th:text="${b.author}">余华</td>
        <td th:text="${b.sales}">200</td>
        <td th:text="${b.stock}">400</td>
            <td>
                <a href="#">修改</a><a href="#" class="del">删除</a>
            </td>
        </tr>
    </tbody>
</table>
3.2.4 图书删除功能
① 思路

book_manager.html→删除超链接→BookServlet.delBookById()→重定向显示列表功能

② 删除超链接
<a th:href="@{/book(method=delBookById,id=${b.id})}" class="del">删除</a>
③ BookServlet.delBookById()
    // 根据id删除图书
    protected void delBookById(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.获取id
        String id = req.getParameter("id");
        int intId = Integer.parseInt(id);
        // 2.调用方法删除
        service.delBookById(intId);
        // 3.重定向到getAll方法
        resp.sendRedirect(req.getContextPath() + "/book?method=getAll");

    }
④ BookService.delBookById()
    @Override
    public void delBookById(int intId) {
        dao.removeBookById(intId);
    }
⑤ BookDao.removeBookById()
    @Override
    public void removeBookById(int intId) {
        String sql = "delete from books where id = ?";
        update(sql, intId);
    }
3.2.5 新增图书功能
① 思路

book_manager.html→添加图书超链接→BookServlet.toAddPage()→book_add.html

book_add.html→提交表单→BookServlet.saveBook()→重定向显示列表功能

② 添加图书超链接

修改book_manager.html页面

<a href="book?method=toAddBookPage">添加图书</a>
③ 实现:BookManagerServlet.toAddPage()
    // 前往添加图书页面
    protected void toAddBookPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processTemplate("manager/book_add", req, resp);
    }
④ 新建book_add.html

由book_edit.html复制出来,然后调整表单标签:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<base th:href="@{/}">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="static/css/minireset.css" />
    <link rel="stylesheet" href="static/css/common.css" />
    <link rel="stylesheet" href="static/css/style.css" />
    <link rel="stylesheet" href="static/css/cart.css" />
    <link rel="stylesheet" href="static/css/bookManger.css" />
    <link rel="stylesheet" href="static/css/register.css" />
    <link rel="stylesheet" href="static/css/book_edit.css" />
  </head>
  <body>
    <div class="header">
      <div class="w">
        <div class="header-left">
          <a href="index.html">
            <img src="static/img/logo.gif" alt=""
          /></a>
          <h1>添加图书</h1>
        </div>
        <div class="header-right" th:include="fragment/menu::commentmenu"></div>
<!--        <div class="header-right">-->
<!--          <a href="./book_manager.html" class="order">图书管理</a>-->
<!--          <a href="./order_manager.html" class="destory">订单管理</a>-->
<!--          <a href="index.html" class="gohome">返回商城</a>-->
<!--        </div>-->
      </div>
    </div>
    <div class="login_banner">
      <div class="register_form">
        <form action="book">
          <input type="hidden" name="method" value="addBook">
          <div class="form-item">
            <div>
              <label>名称:</label>
              <input type="text" placeholder="请输入名称" name="title" />
            </div>
<!--            <span class="errMess" style="visibility: visible;"-->
<!--              >请输入正确的名称</span-->
<!--            >-->
          </div>
          <div class="form-item">
            <div>
              <label>价格:</label>
              <input type="number" placeholder="请输入价格" name="price"/>
            </div>
<!--            <span class="errMess">请输入正确数字</span>-->
          </div>
          <div class="form-item">
            <div>
              <label>作者:</label>
              <input type="text" placeholder="请输入作者" name="author"/>
            </div>
<!--            <span class="errMess">请输入正确作者</span>-->
          </div>
          <div class="form-item">
            <div>
              <label>销量:</label>
              <input type="number" placeholder="请输入销量" name="sales"/>
            </div>
<!--            <span class="errMess">请输入正确销量</span>-->
          </div>
          <div class="form-item">
            <div>
              <label>库存:</label>
              <input type="number" placeholder="请输入库存" name="stock"/>
            </div>
<!--            <span class="errMess">请输入正确库存</span>-->
          </div>

          <button class="btn">提交</button>
        </form>
      </div>
    </div>
    <div class="bottom">
      尚硅谷书城.Copyright ©2015
    </div>
  </body>
</html>

⑤ BookServlet.addBook()
    // 添加图书
    protected void addBook(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.获取输入的数据
        Map<String, String[]> map = req.getParameterMap();
        // 2.创建空对象
        Book book = new Book();
        try {
            // 3.讲数据填入到对象中
            BeanUtils.populate(book, map);
            // 4.调用业务层的方法进行添加图书
            service.addBook(book);
            // 5.添加成功后重定向到getAll方法
            resp.sendRedirect(req.getContextPath() + "/book?method=getAll");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
⑥ BookService.addBook()
@Override
public void addBook(Book book) {

    dao.insertBook(book);
}
⑦ BookDao.insertBook()
@Override
public void insertBook(Book book) {
    // imgPath设置为默认值
    book.setImgPath("static/uploads/xiaowangzi.jpg");
    String sql = "insert into books values(null,?,?,?,?,?,?);";
    update(sql, book.getTitle(), book.getAuthor(), book.getPrice(), book.getSales(), book.getStock(), book.getImgPath());

}
3.2.6 修改图书功能
① 思路

book_manager.html→修改图书超链接→BookServlet.toUpdateBookPage()→book_edit.html(表单回显)

book_edit.html→提交表单→BookServlet.updateBook()→重定向显示列表功能

② 修改图书超链接
<a th:href="@{/book(method=toUpdateBookPage,id=${b.id})}">修改</a>
③ BookServlet.toUpdateBookPage()
// 跳转到更新图书页面
protected void toUpdateBookPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 获取客户端传入的id
    String id = req.getParameter("id");
    int intId = Integer.parseInt(id);
    // 根据id查询图书详情
    Book book = service.getBookById(intId);
    // 将图书信息存储到请求域
    req.setAttribute("book", book);
    processTemplate("manager/book_edit", req, resp);
}
④ BookService.getBookById()
@Override
public Book getBookById(int intId) {
    Book book = dao.selectById(intId);
    return book;
}
⑤ BookDao.selectById()
@Override
public Book selectById(int intId) {
    String sql = "select * from books where id = ?";
    Book book = findOneBean(sql, Book.class, intId);
    return book;
}
⑥ book_edit.html(表单回显)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<base th:href="@{/}">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="static/css/minireset.css" />
    <link rel="stylesheet" href="static/css/common.css" />
    <link rel="stylesheet" href="static/css/style.css" />
    <link rel="stylesheet" href="static/css/cart.css" />
    <link rel="stylesheet" href="static/css/bookManger.css" />
    <link rel="stylesheet" href="static/css/register.css" />
    <link rel="stylesheet" href="static/css/book_edit.css" />
  </head>
  <body>
    <div class="header">
      <div class="w">
        <div class="header-left">
          <a href="index.html">
            <img src="static/img/logo.gif" alt=""
          /></a>
          <h1>编辑图书</h1>
        </div>
        <div class="header-right" th:include="fragment/menu::commentmenu"></div>
<!--        <div class="header-right">-->
<!--          <a href="./book_manager.html" class="order">图书管理</a>-->
<!--          <a href="./order_manager.html" class="destory">订单管理</a>-->
<!--          <a href="index.html" class="gohome">返回商城</a>-->
<!--        </div>-->
      </div>
    </div>
    <div class="login_banner">
      <div class="register_form">
        <form action="book">
          <input type="hidden" name="method" value="updateBookById">
          <div class="form-item">
            <div>
              <input type="hidden" name="id" th:value="${book.id}">
              <label>名称:</label>
              <input type="text" placeholder="请输入名称" name="title" th:value="${book.title}"/>
            </div>
<!--            <span class="errMess" style="visibility: visible;"-->
<!--              >请输入正确的名称</span-->

          </div>
          <div class="form-item">
            <div>
              <label>价格:</label>
              <input type="number" placeholder="请输入价格" name="price" th:value="${book.price}"/>
            </div>
<!--            <span class="errMess">请输入正确数字</span>-->
          </div>
          <div class="form-item">
            <div>
              <label>作者:</label>
              <input type="text" placeholder="请输入作者" name="author" th:value="${book.author}"/>
            </div>
<!--            <span class="errMess">请输入正确作者</span>-->
          </div>
          <div class="form-item">
            <div>
              <label>销量:</label>
              <input type="number" placeholder="请输入销量" name="sales" th:value="${book.sales}"/>
            </div>
<!--            <span class="errMess">请输入正确销量</span>-->
          </div>
          <div class="form-item">
            <div>
              <label>库存:</label>
              <input type="number" placeholder="请输入库存" name="stock" th:value="${book.stock}"/>
            </div>
<!--            <span class="errMess">请输入正确库存</span>-->
          </div>

          <button class="btn">提交</button>
        </form>
      </div>
    </div>
    <div class="bottom">
      尚硅谷书城.Copyright ©2015
    </div>
  </body>
</html>

⑦ BookServlet.updateBookById()
    protected void updateBookById(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1.获取修改后的图书信息
        Map<String, String[]> map = req.getParameterMap();
        // 2.创建Book对象
        Book book = new Book();
        try {
            BeanUtils.populate(book, map);
            // 3.调用业务层对象方法进行修改
            service.updateBook(book);
            // 4.重定向到getAll方法
            resp.sendRedirect(req.getContextPath() + "/book?method=getAll");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
⑧ BookService.updateBook()
@Override
public void updateBook(Book book) {
    dao.updateBook(book);
}
⑨ BookDao.updateBook()

注意:这里不修改imgPath字段

@Override
public void updateBook(Book book) {
    String sql = "update books set title=?,author=?,price=?,sales=?,stock=? where id=?";
    update(sql, book.getTitle(), book.getAuthor(), book.getPrice(), book.getSales(), book.getStock(), book.getId());
}

4. 前台图书展示

4.1 思路

index.html→Index.doPost()→把图书列表数据查询出来→渲染视图→页面迭代显示图书数据

4.2 代码

4.2.1 Index.doPost()
package com.atguigu.servlet.app;

import com.atguigu.pojo.Book;
import com.atguigu.service.BookService;
import com.atguigu.service.impl.BookServiceImpl;
import com.atguigu.servlet.base.ViewBaseServlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

@WebServlet("/index.html")
public class IndexServlet extends ViewBaseServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 创建业务层对象
        BookService service = new BookServiceImpl();
        // 调用业务层方法获取图书
        List<Book> books = service.getAll();
        // 将数据放进请求域
        req.setAttribute("books", books);
        // 跳转到主页
        processTemplate("index", req, resp);
    }
}

4.2.2 页面迭代显示图书数据

页面文件:index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <base th:href="@{/}">
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>书城首页</title>
    <link rel="stylesheet" href="static/css/minireset.css" />
    <link rel="stylesheet" href="static/css/common.css" />
    <link rel="stylesheet" href="static/css/iconfont.css" />
    <link rel="stylesheet" href="static/css/index.css" />
    <link rel="stylesheet" href="static/css/swiper.min.css" />
  </head>
  <body>
  <div id="app">
    <div class="topbar">
      <div class="w">
        <div class="topbar-left">
          <i>送至:</i>
          <i>北京</i>
          <i class="iconfont icon-ai-arrow-down"></i>
        </div>
        <div class="topbar-right">
          <a href="user?method=toLoginPage" class="login">登录</a>
          <a href="user?method=toRegistPage" class="register">注册</a>
          <a
                  href="pages/cart/cart.html"
                  class="cart iconfont icon-gouwuche
			"
          >
            购物车
            <div class="cart-num">3</div>
          </a>
          <a href="admin" class="admin">后台管理</a>
        </div>
<!--          登录后风格-->
<!--          <div class="topbar-right">-->
<!--            <span>欢迎你<b>张总</b></span>-->
<!--            <a href="#" class="register">注销</a>-->
<!--            <a-->
<!--                    href="pages/cart/cart.jsp"-->
<!--                    class="cart iconfont icon-gouwuche-->
<!--			">-->
<!--              购物车-->
<!--              <div class="cart-num">3</div>-->
<!--            </a>-->
<!--            <a href="pages/manager/book_manager.html" class="admin">后台管理</a>-->
<!--          </div>-->
<!--        </div>-->
<!--      </div>-->
      <div class="header w">
        <a href="#" class="header-logo"></a>
        <div class="header-nav">
          <ul>
            <li><a href="#">java</a></li>
            <li><a href="#">前端</a></li>
            <li><a href="#">小说</a></li>
            <li><a href="#">文学</a></li>
            <li><a href="#">青春文学</a></li>
            <li><a href="#">艺术</a></li>
            <li><a href="#">管理</a></li>
          </ul>
        </div>
        <div class="header-search">
          <input type="text" placeholder="十万个为什么" />
          <button class="iconfont icon-search"></button>
        </div>
      </div>
      <div class="banner w clearfix">
        <div class="banner-left">
          <ul>
            <li>
              <a href="">
                <span>文学 鉴赏</span>
                <i class="iconfont icon-jiantou"></i
              ></a>
            </li>
            <li>
              <a href="">
                <span>社科 研究</span>
                <i class="iconfont icon-jiantou"></i
              ></a>
            </li>
            <li>
              <a href="">
                <span>少儿 培训</span>
                <i class="iconfont icon-jiantou"></i
              ></a>
            </li>
            <li>
              <a href="">
                <span>艺术 赏析</span>
                <i class="iconfont icon-jiantou"></i
              ></a>
            </li>
            <li>
              <a href="">
                <span>生活 周边</span>
                <i class="iconfont icon-jiantou"></i
              ></a>
            </li>
            <li>
              <a href="">
                <span>文教 科技</span>
                <i class="iconfont icon-jiantou"></i
              ></a>
            </li>
            <li>
              <a href="">
                <span>热销 畅读</span>
                <i class="iconfont icon-jiantou"></i
              ></a>
            </li>
          </ul>
        </div>
        <div class="banner-right">
          <div class="swiper-container">
            <ul class="swiper-wrapper">
              <li class="swiper-slide">
                <img src="static/uploads/banner4.jpg" alt="">
                <!-- <div class="banner-img"></div> -->
              </li>
              <li class="swiper-slide">
                <img src="static/uploads/banner5.jpg" alt="">
                <!-- <div class="banner-img"></div> -->
              </li>
              <li class="swiper-slide">
                <img src="static/uploads/banner6.jpg" alt="">
                <!-- <div class="banner-img"></div> -->
              </li>
            </ul>
            <div class="swiper-button-prev"></div>

            <div class="swiper-button-next"></div>

            <!-- Add Pagination -->
            <div class="swiper-pagination"></div>
          </div>
        </div>
      </div>
      <div class="books-list ">
        <div class="w">
          <div class="list">
            <div class="list-header">
              <div class="title">图书列表</div>
              <div class="price-search">
                <span>价格:</span>
                <input type="text">
                <span>-元</span>
                <input type="text">
                <span></span>
                <button>查询</button>
              </div>
            </div>
            <div class="list-content">
              <div class="list-item" th:each="book:${books}">
                <img th:src="${book.imgPath}" alt="">
                <p>书名: <span th:text="${book.title}"></span></p>
                <p>作者: <span th:text="${book.author}"></span></p>
                <p>价格: <span th:text="${book.price}"></span></p>
                <p>销量: <span th:text="${book.sales}"></span></p>
                <p>库存: <span th:text="${book.stock}"></span></p>
                <button>加入购物车</button>
              </div>


            </div>
            <div class="list-footer">
                <div>首页</div>
                <div>上一页</div>
                <ul><li class="active">1</li><li>2</li><li>3</li></ul>
                <div>下一页</div>
                <div>末页</div>
                <span>共10页</span>
                <span>30条记录</span>
                <span>到第</span>
                <input type="text">
                <span></span>
                <button>确定</button>
            </div>
          </div>
        </div>

      </div>
      <div class="cate w">
        <div class="list">
          <a href="" class="list-item">
            <i class="iconfont icon-java"></i>
            <span>java</span>
          </a>
          <a href="" class="list-item"
            ><i class="iconfont icon-h5"></i>h5</a
          >
          <a href="" class="list-item">
            <i class="iconfont icon-python"></i>python
          </a>
          <a href="" class="list-item"
            ><i class="iconfont icon-tianchongxing-"></i>pm</a
          >
          <a href="" class="list-item"
            ><i class="iconfont icon-php_elephant"></i>php</a
          >
          <a href="" class="list-item"
            ><i class="iconfont icon-go"></i>go</a
          >
        </div>
        <a href="" class="img">
          <img src="static/uploads/cate4.jpg" alt="" />
        </a>
        <a href="" class="img">
          <img src="static/uploads/cate5.jpg" alt="" />
        </a>
        <a href="" class="img">
          <img src="static/uploads/cate6.jpg" alt="" />
        </a>
      </div>
      <div class="books">
        <div class="w">
          <div class="seckill">
            <div class="seckill-header">
              <div class="title">
                图书秒杀
              </div>
              <!-- <i class="iconfont icon-huanyipi"></i> -->
            </div>
            <div class="seckill-content">

                  <a href="" class="tip">
                     <h5>距离结束还有</h5>
                     <i class="iconfont icon-shandian"></i>
                     <div class="downcount">
                      <span class="time">00</span>
                      <span class="token">:</span>
                      <span class="time">00</span>
                      <span class="token">:</span>
                      <span class="time">00</span>
                     </div>
                  </a>


                  <a href="" class="books-sec">
                    <img src="static/uploads/congwanqingdaominguo.jpg" alt="">
                    <p>从晚晴到民国</p>
                    <div>
                      <span class="cur-price">¥28.9</span>
                      <span class="pre-price">¥36.5</span>
                    </div>
                    <button>立即购买</button>
                  </a>
                  <a href="" class="books-sec">
                    <img src="static/uploads/cyuyanrumenjingdian.jpg" alt="">
                    <p>c语言入门经典</p>
                    <div>
                      <span class="cur-price">¥55.9</span>
                      <span class="pre-price">¥68.5</span>
                    </div>
                    <button>立即购买</button>
                  </a>
                  <a href="" class="books-sec">
                    <img src="static/uploads/fusang.jpg" alt="">
                    <p>扶桑</p>
                    <div>
                      <span class="cur-price">¥30.9</span>
                      <span class="pre-price">¥47.5</span>
                    </div>
                    <button>立即购买</button>
                  </a>
                  <a href="" class="books-sec">
                    <img src="static/uploads/geihaizideshi.jpg" alt="">
                    <p>给孩子的诗</p>
                    <div>
                      <span class="cur-price">¥18.9</span>
                      <span class="pre-price">¥25.5</span>
                    </div>
                    <button>立即购买</button>
                  </a>




              </ul>
            </div>
          </div>
        </div>
      </div>
      <div class="bottom">
        <div class="w">
          <div class="top">
            <ul>
              <li>
                <a href="">
                  <img src="static/img/bottom1.png" alt="">
                  <span>大咖级讲师亲自授课</span>
                </a>
              </li>
              <li>
                <a href="">
                  <img src="static/img/bottom.png" alt="">
                  <span>课程为学员成长持续赋能</span>
                </a>
              </li>
              <li>
                <a href="">
                  <img src="static/img/bottom2.png" alt="">
                  <span>学员真是情况大公开</span>
                </a>
              </li>
            </ul>
          </div>
          <div class="content">
            <dl>
              <dt>关于尚硅谷</dt>
              <dd>教育理念</dd>
              <!-- <dd>名师团队</dd>
              <dd>学员心声</dd> -->
            </dl>
            <dl>
              <dt>资源下载</dt>
              <dd>视频下载</dd>
              <!-- <dd>资料下载</dd>
              <dd>工具下载</dd> -->
            </dl>
            <dl>
              <dt>加入我们</dt>
              <dd>招聘岗位</dd>
              <!-- <dd>岗位介绍</dd>
              <dd>招贤纳师</dd> -->
            </dl>
            <dl>
              <dt>联系我们</dt>
              <dd>http://www.atguigu.com<dd>
            </dl>
          </div>
        </div>
        <div class="down">
          尚硅谷书城.Copyright ©2015
        </div>
      </div>


    </div>
    <script src="static/script/swiper.min.js"></script>
    <script>
      var swiper = new Swiper('.swiper-container', {
        autoplay: true,
        pagination: {
          el: '.swiper-pagination',
          dynamicBullets: true
        },
        navigation: {
          nextEl: '.swiper-button-next',
          prevEl: '.swiper-button-prev'
        }
      })
    </script>
  </body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值