day09 书城项目第三阶段

第一章 项目准备工作

1. 创建Module

day09_书城项目第三阶段 - 图1

2. 拷贝jar包

  1. 数据库jar包
  • day09_书城项目第三阶段 - 图2

  1. Thymeleaf的jar包
  • day09_书城项目第三阶段 - 图3

3. 从V2版本项目迁移代码

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

  • 拷贝resources目录,然后将resource目录标记成Resources Root
  • 拷贝src目录下的内容,并且将原有的Servlet全部删除
  • 创建两个子包
    • 存放Servlet基类:com.atguigu.bookstore.servlet.base
    • 存放Servlet子类:com.atguigu.bookstore.servlet.model
  • 从资料中将两个基类拷贝过来,放置到com.atguigu.bookstore.servlet.base包里面
    • 视图基类:ViewBaseServlet
    • 方法分发基类:ModelBaseServlet

3.2 迁移前端代码

  • 将V02中的pages目录整体复制到V03 module的WEB-INF目录下
  • 将V02中的static目录整体复制到V03 module的web目录下
  • 将V02中的index.html复制到V03 module的WEB-INF/pages目录下,将来通过Servlet访问

4. 显示首页

4.1 修改web.xml



view-prefix
/WEB-INF/pages/


view-suffix
.html

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

4.2 创建PortalServlet

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

PortalServlet
com.atguigu.bookstore.servlet.model.PortalServlet


PortalServlet
/index.html

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

import com.atguigu.servlet.base.ViewBaseServlet;

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

/*
@author Leevi
日期2021-05-14 09:03
该Servlet只需要处理访问首页
*/
public class PortalServlet extends ViewBaseServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

  1. @Override<br /> protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br /> processTemplate("index",request,response);<br /> }<br />}

4.3 调整index.html

  • 加入Thymeleaf名称空间
- 修改base标签 ## 第二章 完成用户模块 ### 1. 重构登录功能 #### 1.1 思路 day09_书城项目第三阶段 - 图4 #### 1.2 代码 ##### 1.2.1 创建UserServlet web.xml中的配置:

UserServlet
com.atguigu.servlet.model.UserServlet

UserServlet
/user

Java代码:
package com.atguigu.servlet.model; import com.atguigu.bean.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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map; /
@author Leevi
日期2021-05-14 09:07
*/
public class UserServlet extends ModelBaseServlet {
private UserService userService = new UserServiceImpl();
/

跳转到登录页面
@param request
@param response
/
public void toLoginPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
}
}
注意:记得修改UserServlet继承的类ModelBaseServlet ##### 1.2.1 前往登录页面功能 ###### 1.2.1.1 修改首页中登录超链接 ###### 1.2.1.2 完成UserServlet.toLoginPage()方法 /
跳转到登录页面
@param request
@param response
/
public void toLoginPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
processTemplate(“user/login”,request,response);
} ###### 1.2.1.3 调整登录页面代码 - 加入Thymeleaf名称空间 - 修改base标签 - 修改form标签action属性
- 增加method请求参数的表单隐藏域 - 根据条件显示登录失败消息 {{errorMessage}} ##### 1.2.3 登录校验功能 UserServlet.doLogin()
/

处理登录校验
@param request
@param response
@throws IOException
/
public void doLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
//还是做原来的登录校验
//1. 获取客户端传入的请求参数
String username = request.getParameter(“username”);
String password = request.getParameter(“password”);
//2. 将username和password封装到User对象
User user = new User(null,username,password,null); //3. 调用业务层的方法处理登录
try {
User loginUser = userService.doLogin(user);
//没有出现异常,说明登录成功,那么跳转到登录成功页面
processTemplate(“user/login_success”,request,response);
} catch (Exception e) {
e.printStackTrace();
//出现异常表示登录失败,则往域对象中存储登录失败的信息
request.setAttribute(“errorMessage”,”登录失败,”+e.getMessage());
//跳转到登录页面,显示登录失败的信息
processTemplate(“user/login”,request,response);
}
} ###### 1.2.3.1 回显表单中的用户名 在login.html页面进行设置
遇到问题:使用th:value=”${param.username}”确实实现了服务器端渲染,但是实际打开页面并没有看到。原因是页面渲染顺序: - 服务器端渲染 - 服务器端将渲染结果作为响应数据返回给浏览器 - 浏览器加载HTML文档 - 读取到Vue代码后,执行Vue代码 - Vue又进行了一次浏览器端渲染,覆盖了服务器端渲染的值 解决办法:将服务器端渲染的结果设置到Vue对象的data属性中。
new Vue({
“el”:”#loginForm”,
“data”:{
“username”:”[[${param.username}]]”,
“password”:””
}, ###### 1.2.3.2 修改login_success.html页面 login_success.html

……
### 2. 重构注册功能 ### 2.1 思路 day09_书城项目第三阶段 - 图5 #### 2.2 代码 ##### 2.2.1 前往注册页面功能 ###### 2.2.1.1 修改首页中注册超链接 注册 ###### 2.2.1.2 完成UserServlet.toRegisterPage()方法 /**
跳转到注册页面
@param request
@param response
@throws IOException
/
public void toRegisterPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
processTemplate(“user/regist”,request,response);
} ###### 2.2.1.3 调整注册页面代码
……

……

……
//注册失败后回显数据
new Vue({
“el”:”#registerForm”,
“data”:{
“username”:”[[${param.username}]]”,
“password”:””,
“passwordConfirm”:””,
“email”:”[[${param.email}]]”,
“code”:””,
“usernameCheckMessage”:””
} ##### 2.2.2 注册功能 /
处理注册请求
@param request
@param response
@throws IOException
*/
public void doRegister(HttpServletRequest request, HttpServletResponse response) throws IOException {
//1. 获取请求参数
Map parameterMap = request.getParameterMap();
//2. 使用BeanUtils将parameterMap中的数据封装到User对象
User user = new User();
try {
BeanUtils.populate(user,parameterMap);
//3. 调用业务层的方法处理注册业务
userService.doRegister(user); //没有异常,就是注册成功
//跳转到注册成功页面
processTemplate(“user/regist_success”,request,response);
} catch (Exception e) {
e.printStackTrace();
//有异常就注册失败,往域对象中存入失败信息
request.setAttribute(“errorMessage”,”注册失败,”+e.getMessage());
//跳转回到注册页面
processTemplate(“user/regist”,request,response);
}
} ###### 2.2.2.1 修改regist_success.html页面
……
## 第三章 书城后台CRUD ### 1. 进入后台页面 #### 1.1 概念辨析 day09_书城项目第三阶段 - 图6 #### 1.2 访问后台首页 ##### 1.2.1 思路 首页→后台系统超链接→AdminServlet.toManagerPage()→manager.html ##### 1.2.2 代码 ###### 1.2.2.1 创建AdminServlet web.xml

AdminServlet
com.atguigu.servlet.model.AdminServlet


AdminServlet
/admin

Java代码:
package com.atguigu.servlet.model; import com.atguigu.servlet.base.ModelBaseServlet; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /

@author Chunsheng Zhang
日期2021-05-14 10:00
/
public class AdminServlet extends ModelBaseServlet {
/**
跳转到后台管理界面
@param request
@param response
*/
public void toManagerPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
processTemplate(“manager/manager”,request,response);
}
} ###### 1.2.2.2 调整manager.html


然后去除页面上的所有“../” ###### 1.2.2.3 抽取页面公共部分 1. 创建包含代码片段的页面 day09_书城项目第三阶段 - 图7 admin-navigator.html的代码
<!DOCTYPE html>








  1. 在有需要的页面(book_edit.html、book_manager.html、order_manager.html)引入片段

2. 后台图书CRUD

2.1 数据建模

2.1.1 物理建模

执行资料中的sql脚本,一定要注意:不要重新创建数据库(建议照着视频做)

2.1.2 逻辑建模

package com.atguigu.bean;

/*
包名:com.atguigu.bean

@author Chunsheng Zhang
日期2021-05-14 10:22
/
public class Book {
private Integer bookId;
private String bookName;
private String author;
private Double price;
private Integer sales;
private Integer stock;
private String imgPath;

public Book() {<br />    }

public Book(Integer bookId, String bookName, String author, Double price, Integer sales, Integer stock, String imgPath) {<br />        this.bookId = bookId;<br />        this.bookName = bookName;<br />        this.author = author;<br />        this.price = price;<br />        this.sales = sales;<br />        this.stock = stock;<br />        this.imgPath = imgPath;<br />    }

@Override<br />    public String toString() {<br />        return "Book{" +<br />                "bookId=" + bookId +<br />                ", bookName='" + bookName + '\'' +<br />                ", author='" + author + '\'' +<br />                ", price=" + price +<br />                ", sales=" + sales +<br />                ", stock=" + stock +<br />                ", imgPath='" + imgPath + '\'' +<br />                '}';<br />    }

public Integer getBookId() {<br />        return bookId;<br />    }

public void setBookId(Integer bookId) {<br />        this.bookId = bookId;<br />    }

public String getBookName() {<br />        return bookName;<br />    }

public void setBookName(String bookName) {<br />        this.bookName = bookName;<br />    }

public String getAuthor() {<br />        return author;<br />    }

public void setAuthor(String author) {<br />        this.author = author;<br />    }

public Double getPrice() {<br />        return price;<br />    }

public void setPrice(Double price) {<br />        this.price = price;<br />    }

public Integer getSales() {<br />        return sales;<br />    }

public void setSales(Integer sales) {<br />        this.sales = sales;<br />    }

public Integer getStock() {<br />        return stock;<br />    }

public void setStock(Integer stock) {<br />        this.stock = stock;<br />    }

public String getImgPath() {<br />        return imgPath;<br />    }

public void setImgPath(String imgPath) {<br />        this.imgPath = imgPath;<br />    }<br />}

2.2 创建并组装组件

2.2.1 创建Servlet
  • 后台:BookManagerServlet

2.2.2 创建BookService
  • 接口:BookService
  • 实现类:BookServiceImpl

2.2.3 创建BookDao
  • 接口:BookDao
  • 实现类:BookDaoImpl

2.2.4 组装
  • 给BookManagerServlet组装BookService
  • 给BookService组装BookDao

2.3 图书列表显示功能

2.3.1 思路

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

2.3.2 修改图书管理超链接

超链接所在文件位置:
WEB-INF/pages/segment/admin-navigator.html
图书管理

2.3.3 BookManagerServlet.showBookList()

/*
跳转到图书管理页面
@param request
@param response
*/
public void toBookManagerPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
try {
//查询出图书列表
List bookList = bookService.getBookList();
//将图书列表存储到请求域
request.setAttribute(“bookList”,bookList);
processTemplate(“manager/book_manager”,request,response);
} catch (Exception e) {
e.printStackTrace();
}
}

2.3.4 BookService.getBookList()

@Override
public List getBookList() throws Exception{
return bookDao.selectBookList();
}

2.3.5 BookDao.selectBookList()

@Override
public List selectBookList() throws SQLException{
String sql = “select book_id bookId,book_name bookName,author,price,sales,stock,img_path imgPath from t_book”;

return getBeanList(Book.class,sql);<br />}

2.3.6 调整book_manager.html
  • Thymeleaf名称空间: xmlns:th=”http://www.thymeleaf.org
  • base标签:
  • 替换页面路径中的../
  • 包含进来的代码片段:

2.3.7 在book_manager.html中迭代显示图书列表




























图片 商品名称 价格 作者 销量 库存 操作
图书列表为空,请先添加图书!!!

day09_书城项目第三阶段 - 图8
活着
100.00
余华 200 400
修改删除

2.4 图书删除功能

2.4.1 思路

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

2.4.2 删除超链接

删除

2.4.3 BookManagerServlet.removeBook()

/*
删除图书
@param request
@param response
@throws IOException
/
public void removeBook(HttpServletRequest request, HttpServletResponse response) throws IOException {
//1. 获取要删除的图书的id
Integer id = Integer.valueOf(request.getParameter(“id”));
//2. 调用业务层的方法根据id删除图书
try {
bookService.removeBook(id);
//3. 删除成功,重新查询所有图书信息
response.sendRedirect(request.getContextPath()+”/bookManager?method=toBookManagerPage”);
} catch (Exception e) {
e.printStackTrace();
}
}

2.4.4 BookService.removeBook()

@Override
public void removeBook(Integer bookId) throws Exception {
bookDao.deleteBook(bookId);
}

2.4.5 BookDao.deleteBook()

@Override
public void deleteBook(Integer bookId) throws SQLException {
String sql = “delete from t_book where book_id=?”;
update(sql,bookId);
}

2.5 新增图书功能

2.5.1 思路

book_manager.html→添加图书超链接→BookManagerServlet.toAddPage()→book_add.html
book_add.html→提交表单→BookManagerServlet.saveBook()→重定向显示列表功能

2.5.2 添加图书超链接

修改book_manager.html页面
添加图书

2.5.3 实现:BookManagerServlet.toAddPage()

/*
跳转到添加图书页面
@param request
@param response
@throws IOException
/
public void toAddPage(HttpServletRequest request, HttpServletResponse response) throws IOException{
processTemplate(“manager/book_edit”,request,response);
}

2.5.4 book_edit.html

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












请输入正确数字






请输入正确作者






请输入正确销量






请输入正确库存

<button type="submit" class="btn">提交</button><br /></form>

2.5.5 BookManagerServlet.saveOrUpdateBook()

/*
添加或者图书信息
@param request
@param response
@throws IOException
/
public void saveOrUpdateBook(HttpServletRequest request, HttpServletResponse response) throws IOException{
//1. 获取请求参数
Map parameterMap = request.getParameterMap();
//2. 将parameterMap中的数据封装到Book对象
try {
Book book = new Book();
BeanUtils.populate(book,parameterMap);

    //判断到底是修改还是添加<br />        if (book.getBookId() != null && !"".equals(book.getBookId())) {<br />            //修改图书信息<br />            //TODO<br />        }else {<br />            //添加图书信息<br />            //设置一个固定的imgPath<br />            book.setImgPath("static/uploads/xiaowangzi.jpg");<br />            //3. 调用业务层的方法保存图书信息<br />            bookService.saveBook(book);<br />        }

    //4. 保存成功,则重新查询所有图书<br />        response.sendRedirect(request.getContextPath()+"/bookManager?method=toBookManagerPage");<br />    } catch (Exception e) {<br />        e.printStackTrace();<br />    }<br />}

2.5.6 BookService.saveBook()

@Override
public void saveBook(Book book) throws Exception {
bookDao.insertBook(book);
}

2.5.7 BookDao.insertBook()

@Override
public void insertBook(Book book) throws SQLException {
String sql = “insert into t_book (book_name,author,price,sales,stock,img_path) values (?,?,?,?,?,?)”;
update(sql,book.getBookName(),book.getAuthor(),book.getPrice(),book.getSales(),book.getStock(),book.getImgPath());
}

2.6 修改图书功能

2.6.1 思路

book_manager.html→修改图书超链接→BookManagerServlet.toEditPage()→book_edit.html(表单回显)
book_edit.html→提交表单→BookManagerServlet.updateBook()→重定向显示列表功能

2.6.2 修改图书超链接

修改

2.6.3 BookManagerServlet.toEditPage()

/*
跳转到修改页面
@param request
@param response
@throws IOException
/
public void toEditPage(HttpServletRequest request, HttpServletResponse response) throws IOException{
//获取客户端传入的id
Integer id = Integer.valueOf(request.getParameter(“id”));
try {
//根据id查询图书详情
Book book = bookService.getBookById(id);
//将图书信息存储到请求域
request.setAttribute(“book”,book);
processTemplate(“manager/book_edit”,request,response);
} catch (Exception e) {
e.printStackTrace();
}
}

2.6.4 BookService.getBookById()

@Override
public Book getBookById(Integer bookId) throws Exception{

return bookDao.selectBookByPrimaryKey(bookId);<br />}

2.6.5 BookDao.selectBookByPrimaryKey()

@Override
public Book selectBookByPrimaryKey(Integer bookId) throws SQLException {
String sql = “select book_id bookId,book_name bookName,author,price,sales,stock,img_path imgPath from t_book where book_id=?”;

return getBean(Book.class,sql,bookId);<br />}

2.6.6 book_edit.html(表单回显)
















请输入正确数字






请输入正确作者






请输入正确销量






请输入正确库存

<button type="submit" class="btn">提交</button><br /></form>














请输入正确数字






请输入正确作者






请输入正确销量






请输入正确库存

<button type="submit" class="btn">提交</button><br /></form>

2.6.7 BookManagerServlet.saveOrUpdateBook()

/*
添加或者图书信息
@param request
@param response
@throws IOException
/
public void saveOrUpdateBook(HttpServletRequest request, HttpServletResponse response) throws IOException{
//1. 获取请求参数
Map parameterMap = request.getParameterMap();
//2. 将parameterMap中的数据封装到Book对象
try {
Book book = new Book();
BeanUtils.populate(book,parameterMap);

    //判断到底是修改还是添加<br />        if (book.getBookId() != null && !"".equals(book.getBookId())) {<br />            //修改图书信息<br />            bookService.editBook(book);<br />        }else {<br />            //添加图书信息<br />            //设置一个固定的imgPath<br />            book.setImgPath("static/uploads/xiaowangzi.jpg");<br />            //3. 调用业务层的方法保存图书信息<br />            bookService.saveBook(book);<br />        }

    //4. 保存成功,则重新查询所有图书<br />        response.sendRedirect(request.getContextPath()+"/bookManager?method=toBookManagerPage");<br />    } catch (Exception e) {<br />        e.printStackTrace();<br />    }<br />}

2.6.8 BookService.editBook()

@Override
public void editBook(Book book) throws Exception {
bookDao.updateBook(book);
}

2.6.9 BookDao.updateBook()

注意:这里不修改imgPath字段
@Override
public void updateBook(Book book) throws SQLException {
//我们暂时不修改图片路径
String sql = “update t_book set book_name=?,price=?,author=?,sales=?,stock=? where book_id=?”;

update(sql,book.getBookName(),book.getPrice(),book.getAuthor(),book.getSales(),book.getStock(),book.getBookId());<br />}

第四章 前台图书展示

1. 思路

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

2. 代码

2.1 PortalServlet.doPost()

package com.atguigu.servlet.model;

import com.atguigu.bean.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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/*
@author Chunsheng Zhang
日期2021-05-14 09:03
该Servlet只需要处理访问首页
*/
public class PortalServlet extends ViewBaseServlet {
private BookService bookService = new BookServiceImpl();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

@Override<br />    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {<br />        try {<br />            //查询动态数据<br />            List<Book> bookList = bookService.getBookList();<br />            //将动态数据存储到请求域<br />            request.setAttribute("bookList",bookList);<br />            processTemplate("index",request,response);<br />        } catch (Exception e) {<br />            e.printStackTrace();<br />        }<br />    }<br />}

2.2 页面迭代显示图书数据

页面文件:index.html





图书列表





day09_书城项目第三阶段 - 图9

书名:活着


作者:余华


价格:¥66.6


销量:230


库存:1000



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