day09 书城项目第三阶段
1. 项目准备工作
1.1 创建Module
1.2 拷贝jar包
- 数据库jar包
- 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. 抽取页面公共部分
- 创建包含代码片段的页面
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>
- 在有需要的页面(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>