书城项目-购物车模块的分析、书城项目-购物车模型的创建、书城项目-购物车功能方法的实现和测试、书城项目-添加商品到购物车功能的实现、书城项目-购物车的展示、书城项目-删除购物车中的商品项、书城项目-清空购物车的实现、书城项目-修改购物车商品数量、书城项目-首页购物车数据展示、书城项目-订单模块的分析、书城项目-创建订单模型的数据库表、书城项目-编写订单模块的两个数据模型Order和OrderItem、书城项目-编写订单模块的Dao和测试、书城项目-编写订单模块的Service和测试、书城项目-结账功能实现,生成订单、书城项目-解决生成订单的bug
书城项目第六、七阶段
1、项目第六阶段:购物车
1.1、购物车模块分析
1.2、购物车模型编写
1.2.1、购物车模型:
package top.qaqaq.pojo;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author RichieZhang
* @create 2022-12-13 下午 7:00
*/
/**
* 购物车对象
*/
public class Cart {
// private Integer totalCount; //总商品数量
// private BigDecimal totalPrice; //总商品金额
/**
* key是商品编号,
* value,是商品信息
*/
private Map<Integer,CartItem> items = new LinkedHashMap<Integer,CartItem>(); //购物车商品
/**
* 添加商品项
* @param cartItem
*/
public void addItem(CartItem cartItem){
// 先查看购物车中是否已经添加过此商品,如果已添加,则数量累加,总金额更新,
// 如果没有添加过,直接放到集合中即可
CartItem item = items.get(cartItem.getId());
if (item == null) {
// 之前没添加过此商品
items.put(cartItem.getId(),cartItem);
} else {
// 已经 添加过的情况
item.setCount(item.getCount() + 1); // 数量 累加
item.setTotalPrice( item.getPrice().multiply(new BigDecimal(item.getCount()))); // 更新 总金额
}
}
/**
* 删除商品项
* @param id
*/
public void deleteItem(Integer id){
items.remove(id);
}
/**
* 清空购物车
*/
public void clear(){
items.clear();
}
/**
* 修改商品数量
* @param id
*/
public void updateCount(Integer id, Integer count){
// 先查看购物车中是否有此商品。如果有,修改商品数量,更新总金额
CartItem cartItem = items.get(id);
if (cartItem != null) {
cartItem.setCount(count); // 修改商品数量
cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount()))); // 更新 总金额
}
}
public Cart() {
}
public Integer getTotalCount() {
Integer totalCount = 0; //总商品数量
for (Map.Entry<Integer,CartItem> entry : items.entrySet()) {
totalCount += entry.getValue().getCount();
}
// 或
// for (CartItem value : items.values()) {
// totalCount += value.getCount();
// }
return totalCount;
}
public BigDecimal getTotalPrice() {
BigDecimal totalPrice = new BigDecimal(0); //总商品金额
for (Map.Entry<Integer,CartItem> entry : items.entrySet()) {
totalPrice = totalPrice.add(entry.getValue().getTotalPrice());
}
return totalPrice;
}
public Map<Integer, CartItem> getItems() {
return items;
}
public void setItems(Map<Integer, CartItem> items) {
this.items = items;
}
@Override
public String toString() {
return "Cart{" +
"totalCount=" + getTotalCount() +
", totalPrice=" + getTotalPrice() +
", items=" + items +
'}';
}
}
package top.qaqaq.pojo;
import java.math.BigDecimal;
/**
* @author RichieZhang
* @create 2022-12-13 下午 6:57
*/
/**
* 购物车的商品项
*/
public class CartItem {
private Integer id; //商品编号
private String name; //商品名称
private Integer count; //商品数量
private BigDecimal price; //商品单价
private BigDecimal totalPrice; //商品总价
public CartItem() {
}
public CartItem(Integer id, String name, Integer count, BigDecimal price, BigDecimal totalPrice) {
this.id = id;
this.name = name;
this.count = count;
this.price = price;
this.totalPrice = totalPrice;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
@Override
public String toString() {
return "CartItem{" +
"id=" + id +
", name='" + name + '\'' +
", count=" + count +
", price=" + price +
", totalPrice=" + totalPrice +
'}';
}
}
1.2.2、购物车的测试:
package top.qaqaq.test;
import org.junit.Test;
import top.qaqaq.pojo.Cart;
import top.qaqaq.pojo.CartItem;
import java.math.BigDecimal;
import static org.junit.Assert.*;
/**
* @author RichieZhang
* @create 2022-12-13 下午 7:37
*/
public class CartTest {
@Test
public void addItem() {
Cart cart = new Cart();
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(2,"数据结构与算法",1,new BigDecimal(100),new BigDecimal(100)));
System.out.println(cart);
}
@Test
public void deleteItem() {
Cart cart = new Cart();
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(2,"数据结构与算法",1,new BigDecimal(100),new BigDecimal(100)));
cart.deleteItem(1);
System.out.println(cart);
}
@Test
public void clear() {
Cart cart = new Cart();
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(2,"数据结构与算法",1,new BigDecimal(100),new BigDecimal(100)));
cart.deleteItem(1);
cart.clear();
System.out.println(cart);
}
@Test
public void updateCount() {
Cart cart = new Cart();
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(2,"数据结构与算法",1,new BigDecimal(100),new BigDecimal(100)));
cart.deleteItem(1);
cart.clear();
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.updateCount(1,10);
System.out.println(cart);
}
}
1.3、加入购物车功能的实现
CartServlet 程序中的代码:
package top.qaqaq.web;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.qaqaq.pojo.Book;
import top.qaqaq.pojo.Cart;
import top.qaqaq.pojo.CartItem;
import top.qaqaq.service.BookService;
import top.qaqaq.service.impl.BookServiceImpl;
import top.qaqaq.utils.WebUtils;
import java.io.IOException;
/**
* @author RichieZhang
* @create 2022-12-13 下午 8:06
*/
public class CartServlet extends BaseServlet{
private BookService bookService = new BookServiceImpl();
/**
* 加入购物车
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println("加入购物车");
// System.out.println("商品编号:" + req.getParameter("id"));
// 获取请求的参数 商品编号
int id = WebUtils.parseInt(req.getParameter("id"),0);
// 调用bookService.queryBookById(id):Book得到图书的信息
Book book = bookService.queryBookById(id);
// 把图书信息,转换成为CartItem商品项
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 调用Cart.addItem(CartItem);添加商品项
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
System.out.println(cart);
System.out.println("请求头Referer的值:" + req.getHeader("Referer"));
// 重定向回原来商品所在的地址页面
resp.sendRedirect(req.getHeader("Referer"));
}
/**
* 测试Referer
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void Test(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("请求头Referer的值:" + req.getHeader("Referer"));
}
}
index.jsp 页面 js 的代码:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>书城首页</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
<script type="text/javascript">
$(function () {
// 给加入购物车按钮绑定单击事件
$("button.addToCart").click(function () {
/**
* 在事件响应的function函数 中,有一个this对象,这个this对象,是当前正在响应事件的dom对象
* @type {*|jQuery}
*/
var bookId = $(this).attr("bookId");
location.href = "http://localhost:8080/JavaWeb_Code_Book/cartServlet?action=addItem&id=" + bookId;
})
})
</script>
</head>
<body>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
<span class="wel_word">网上书城</span>
<div>
<%-- 如果用户还没有登录,显示 【登录 和注册的菜单】 --%>
<c:if test="${empty sessionScope.user}">
<a href="pages/user/login.jsp">登录</a> |
<a href="pages/user/regist.jsp">注册</a>
</c:if>
<%-- 如果已经登录,则显示 登录 成功之后的用户信息。 --%>
<c:if test="${not empty sessionScope.user}">
<span>欢迎<span class="um_span">${sessionScope.user.username}</span>光临尚硅谷书城</span>
<a href="pages/order/order.jsp">我的订单</a>
<a href="userServlet?action=logout">注销</a>
</c:if>
<a href="pages/cart/cart.jsp">购物车</a>
<a href="pages/manager/manager.jsp">后台管理</a>
</div>
</div>
<div id="main">
<div id="book">
<div class="book_cond">
<form action="client/bookServlet" method="get">
<input type="hidden" name="action" value="pageByPrice">
价格:<input id="min" type="text" name="min" value="${param.min}"> 元 -
<input id="max" type="text" name="max" value="${param.max}"> 元
<input type="submit" value="查询" />
</form>
</div>
<div style="text-align: center">
<span>您的购物车中有3件商品</span>
<div>
您刚刚将<span style="color: red">时间简史</span>加入到了购物车中
</div>
</div>
<c:forEach items="${requestScope.page.itmes}" var="book">
<div class="b_list">
<div class="img_div">
<img class="book_img" alt="" src="${book.imgpath}" />
</div>
<div class="book_info">
<div class="book_name">
<span class="sp1">书名:</span>
<span class="sp2">${book.name}</span>
</div>
<div class="book_author">
<span class="sp1">作者:</span>
<span class="sp2">${book.author}</span>
</div>
<div class="book_price">
<span class="sp1">价格:</span>
<span class="sp2">${book.price}</span>
</div>
<div class="book_sales">
<span class="sp1">销量:</span>
<span class="sp2">${book.sales}</span>
</div>
<div class="book_amount">
<span class="sp1">库存:</span>
<span class="sp2">${book.stock}</span>
</div>
<div class="book_add">
<button bookId="${book.id}" class="addToCart">加入购物车</button>
</div>
</div>
</div>
</c:forEach>
</div>
<%-- 静态包含分页条 --%>
<%@include file="/pages/common/page_nav.jsp"%>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
图解说明,如何跳回添加商品的页面:
1.4、购物车的展示
cart.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>购物车</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
</head>
<body>
<%--${sessionScope}--%>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
<span class="wel_word">购物车</span>
<%-- 静态包含,登陆成功之后的菜单 --%>
<%@ include file="/pages/common/login_success_menu.jsp"%>
</div>
<div id="main">
<table>
<tr>
<td>商品名称</td>
<td>数量</td>
<td>单价</td>
<td>金额</td>
<td>操作</td>
</tr>
<c:if test="${empty sessionScope.cart.items}">
<%-- 如果购物车空的情况 --%>
<tr>
<td colspan="5"><a href="index.jsp">亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!</a> </td>
</tr>
</c:if>
<c:if test="${not empty sessionScope.cart.items}">
<%-- 如果购物车非空的情况 --%>
<c:forEach items="${sessionScope.cart.items}" var="entry">
<tr>
<td>${entry.value.name}</td>
<td>${entry.value.count}</td>
<td>${entry.value.price}</td>
<td>${entry.value.totalPrice}</td>
<td><a href="#">删除</a></td>
</tr>
</c:forEach>
</c:if>
</table>
<%-- 如果购物车非空才输出页面的内容 --%>
<c:if test="${not empty sessionScope.cart.items}">
<div class="cart_info">
<span class="cart_span">购物车中共有<span class="b_count">${sessionScope.cart.totalCount}</span>件商品</span>
<span class="cart_span">总金额<span class="b_price">${sessionScope.cart.totalPrice}</span>元</span>
<span class="cart_span"><a href="#">清空购物车</a></span>
<span class="cart_span"><a href="pages/cart/checkout.jsp">去结账</a></span>
</div>
</c:if>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
1.5、删除购物车商品项
CartServlet 程序:
package top.qaqaq.web;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.qaqaq.pojo.Book;
import top.qaqaq.pojo.Cart;
import top.qaqaq.pojo.CartItem;
import top.qaqaq.service.BookService;
import top.qaqaq.service.impl.BookServiceImpl;
import top.qaqaq.utils.WebUtils;
import java.io.IOException;
/**
* @author RichieZhang
* @create 2022-12-13 下午 8:06
*/
public class CartServlet extends BaseServlet{
private BookService bookService = new BookServiceImpl();
/**
* 修改商品数量
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void updateCount(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数 商品编号、商品数量
int id = WebUtils.parseInt(req.getParameter("id"),0);
int count = WebUtils.parseInt(req.getParameter("count"),1);
// 获取Cart购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart != null) {
// 修改商品数量
cart.updateCount(id,count);
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
/**
* 清空购物车
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void clear(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart != null) {
// 清空购物车
cart.clear();
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
/**
* 删除 商品项
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void deleteItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取商品编号
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart != null) {
// 删除 了购物车商品项
cart.deleteItem(id);
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
/**
* 加入购物车
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println("加入购物车");
// System.out.println("商品编号:" + req.getParameter("id"));
// 获取请求的参数 商品编号
int id = WebUtils.parseInt(req.getParameter("id"),0);
// 调用bookService.queryBookById(id):Book得到图书的信息
Book book = bookService.queryBookById(id);
// 把图书信息,转换成为CartItem商品项
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 调用Cart.addItem(CartItem);添加商品项
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
System.out.println(cart);
System.out.println("请求头Referer的值:" + req.getHeader("Referer"));
// 最后一个添加的商品名称
req.getSession().setAttribute("lastName", cartItem.getName());
// 重定向回原来商品所在的地址页面
resp.sendRedirect(req.getHeader("Referer"));
}
/**
* 测试Referer
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void Test(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("请求头Referer的值:" + req.getHeader("Referer"));
}
}
购物车/pages/cart/cart.jsp 页面的代码:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>购物车</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
<script type="text/javascript">
$(function () {
// 给 【删除】绑定单击事件
$("a.deleteItem").click(function () {
return confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() + "】吗?");
})
// 给 清空购物车绑定单击事件
$("#clearCart").click(function () {
return confirm("你确定要清空购物车吗?")
})
// 给 输入框绑定失去焦点事件 === onchange内容发生改变事件
// $(".updateCount").blur(function () {
$(".updateCount").change(function () {
// alert("11");
// 获取商品名称
var name = $(this).parent().parent().find("td:first").text();
var id = $(this).attr("bookId");
// 获取商品数量
var count = this.value;
if (confirm("你确定要将【" + name + "】商品修改数量为:" + count + " 吗?")) {
// 发起请求。给服务器保存修改
location.href = "http://localhost:8080/JavaWeb_Code_Book/cartServlet?action=updateCount&count=" + count + "&id=" + id;
} else {
// defaultValue属性是表单项Dom对象的属性。它表示默认的value属性值。
this.value = this.defaultValue
}
})
})
</script>
</head>
<body>
<%--${sessionScope}--%>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
<span class="wel_word">购物车</span>
<%-- 静态包含,登陆成功之后的菜单 --%>
<%@ include file="/pages/common/login_success_menu.jsp"%>
</div>
<div id="main">
<table>
<tr>
<td>商品名称</td>
<td>数量</td>
<td>单价</td>
<td>金额</td>
<td>操作</td>
</tr>
<c:if test="${empty sessionScope.cart.items}">
<%-- 如果购物车空的情况 --%>
<tr>
<td colspan="5"><a href="index.jsp">亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!</a> </td>
</tr>
</c:if>
<c:if test="${not empty sessionScope.cart.items}">
<%-- 如果购物车非空的情况 --%>
<c:forEach items="${sessionScope.cart.items}" var="entry">
<tr>
<td>${entry.value.name}</td>
<td>
<input class="updateCount" style="width: 60px;"
bookId="${entry.value.id}"
type="text" value="${entry.value.count}">
</td>
<td>${entry.value.price}</td>
<td>${entry.value.totalPrice}</td>
<td><a class="deleteItem" href="cartServlet?action=deleteItem&id=${entry.value.id}">删除</a></td>
</tr>
</c:forEach>
</c:if>
</table>
<%-- 如果购物车非空才输出页面的内容 --%>
<c:if test="${not empty sessionScope.cart.items}">
<div class="cart_info">
<span class="cart_span">购物车中共有<span class="b_count">${sessionScope.cart.totalCount}</span>件商品</span>
<span class="cart_span">总金额<span class="b_price">${sessionScope.cart.totalPrice}</span>元</span>
<span class="cart_span"><a id="clearCart" href="cartServlet?action=clear">清空购物车</a></span>
<span class="cart_span"><a href="orderServlet?action=createOrder">去结账</a></span>
</div>
</c:if>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
删除的请求地址:
删除的确认提示操作:
<script type="text/javascript">
$(function () {
// 给 【删除】绑定单击事件
$("a.deleteItem").click(function () {
return confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() +"】吗?")});
});
</script>
1.6、清空购物车
/**
* 清空购物车
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void clear(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart != null) {
// 清空购物车
cart.clear();
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
cart.jsp 页面的内容
给清空购物车添加请求地址,和添加 id 属性:
清空的确认提示操作:
// 给清空购物车绑定单击事件
$("#clearCart").click(function () {
return confirm("你确定要清空购物车吗?");})
1.7、修改购物车商品数量
/**
* 修改商品数量
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void updateCount(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数 商品编号、商品数量
int id = WebUtils.parseInt(req.getParameter("id"),0);
int count = WebUtils.parseInt(req.getParameter("count"),1);
// 获取Cart购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart != null) {
// 修改商品数量
cart.updateCount(id,count);
// 重定向回原来购物车展示页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
修改 pages/cart/cart.jsp 购物车页面:
修改商品数量 js 代码:
// 给 输入框绑定失去焦点事件 === onchange内容发生改变事件
// $(".updateCount").blur(function () {
$(".updateCount").change(function () {
// alert("11");
// 获取商品名称
var name = $(this).parent().parent().find("td:first").text();
var id = $(this).attr("bookId");
// 获取商品数量
var count = this.value;
if (confirm("你确定要将【" + name + "】商品修改数量为:" + count + " 吗?")) {
// 发起请求。给服务器保存修改
location.href = "http://localhost:8080/JavaWeb_Code_Book/cartServlet?action=updateCount&count=" + count + "&id=" + id;
} else {
// defaultValue属性是表单项Dom对象的属性。它表示默认的value属性值。
this.value = this.defaultValue
}
})
1.8、首页,购物车数据回显
在添加商品到购物车的时候,保存最后一个添加的商品名称:
/**
* 加入购物车
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// System.out.println("加入购物车");
// System.out.println("商品编号:" + req.getParameter("id"));
// 获取请求的参数 商品编号
int id = WebUtils.parseInt(req.getParameter("id"),0);
// 调用bookService.queryBookById(id):Book得到图书的信息
Book book = bookService.queryBookById(id);
// 把图书信息,转换成为CartItem商品项
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 调用Cart.addItem(CartItem);添加商品项
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
System.out.println(cart);
System.out.println("请求头Referer的值:" + req.getHeader("Referer"));
// 最后一个添加的商品名称
req.getSession().setAttribute("lastName", cartItem.getName());
// 重定向回原来商品所在的地址页面
resp.sendRedirect(req.getHeader("Referer"));
}
在 pages/client/index.jsp 页面中输出购物车信息:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>书城首页</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
<script type="text/javascript">
$(function () {
// 给加入购物车按钮绑定单击事件
$("button.addToCart").click(function () {
/**
* 在事件响应的function函数 中,有一个this对象,这个this对象,是当前正在响应事件的dom对象
* @type {*|jQuery}
*/
var bookId = $(this).attr("bookId");
location.href = "http://localhost:8080/JavaWeb_Code_Book/cartServlet?action=addItem&id=" + bookId;
})
})
</script>
</head>
<body>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
<span class="wel_word">网上书城</span>
<div>
<%-- 如果用户还没有登录,显示 【登录 和注册的菜单】 --%>
<c:if test="${empty sessionScope.user}">
<a href="pages/user/login.jsp">登录</a> |
<a href="pages/user/regist.jsp">注册</a>
</c:if>
<%-- 如果已经登录,则显示 登录 成功之后的用户信息。 --%>
<c:if test="${not empty sessionScope.user}">
<span>欢迎<span class="um_span">${sessionScope.user.username}</span>光临尚硅谷书城</span>
<a href="pages/order/order.jsp">我的订单</a>
<a href="userServlet?action=logout">注销</a>
</c:if>
<a href="pages/cart/cart.jsp">购物车</a>
<a href="pages/manager/manager.jsp">后台管理</a>
</div>
</div>
<div id="main">
<div id="book">
<div class="book_cond">
<form action="client/bookServlet" method="get">
<input type="hidden" name="action" value="pageByPrice">
价格:<input id="min" type="text" name="min" value="${param.min}"> 元 -
<input id="max" type="text" name="max" value="${param.max}"> 元
<input type="submit" value="查询" />
</form>
</div>
<div style="text-align: center">
<c:if test="${empty sessionScope.cart.items}">
<%-- 购物车为空的输出 --%>
<span></span>
<div>
<span style="color: red">当前购物车为空</span>
</div>
</c:if>
<c:if test="${not empty sessionScope.cart.items}">
<%-- 购物车非空的输出 --%>
<span>您的购物车中有${sessionScope.cart.totalCount}件商品</span>
<div>
您刚刚将<span style="color: red">${sessionScope.lastName}</span>加入到了购物车中
</div>
</c:if>
</div>
<c:forEach items="${requestScope.page.itmes}" var="book">
<div class="b_list">
<div class="img_div">
<img class="book_img" alt="" src="${book.imgpath}" />
</div>
<div class="book_info">
<div class="book_name">
<span class="sp1">书名:</span>
<span class="sp2">${book.name}</span>
</div>
<div class="book_author">
<span class="sp1">作者:</span>
<span class="sp2">${book.author}</span>
</div>
<div class="book_price">
<span class="sp1">价格:</span>
<span class="sp2">${book.price}</span>
</div>
<div class="book_sales">
<span class="sp1">销量:</span>
<span class="sp2">${book.sales}</span>
</div>
<div class="book_amount">
<span class="sp1">库存:</span>
<span class="sp2">${book.stock}</span>
</div>
<div class="book_add">
<button bookId="${book.id}" class="addToCart">加入购物车</button>
</div>
</div>
</div>
</c:forEach>
</div>
<%-- 静态包含分页条 --%>
<%@include file="/pages/common/page_nav.jsp"%>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
2、项目第七阶段:订单
2.1、订单模块的分析:
2.2:订单模块的实现
2.2.1、创建订单模块的数据库表
# P287 书城项目-创建订单模型的数据库表
USE book;
CREATE TABLE t_order(
order_id VARCHAR(50) PRIMARY KEY, #订单号(唯一)
create_time DATETIME, #下单时间
price DECIMAL(11,2), #金额
status INT, #0未发货,1已发货,2已签收
user_id INT, #用户编号
FOREIGN KEY(user_id) REFERENCES t_user(id)
);
CREATE TABLE t_order_item(
id INT PRIMARY KEY AUTO_INCREMENT, #主键编号
name VARCHAR(100), #商品名称
count INT, #数量
price DECIMAL(11,2), #单价
total_price DECIMAL(11,2), #总价
order_id VARCHAR(50), #订单号
FOREIGN KEY(order_id) REFERENCES t_order(order_id)
);
2.2.2、创建订单模块的数据模型
package top.qaqaq.pojo;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author RichieZhang
* @create 2022-12-14 下午 4:10
*/
public class Order {
private String orderId; //订单号(唯一)
private Date createTime; //下单时间
private BigDecimal price; //金额
// 0未发货,1已发货,2表示已签收
private Integer status = 0; //状态
private Integer userId; //用户编号
public Order() {
}
public Order(String orderId, Date createTime, BigDecimal price, Integer status, Integer userId) {
this.orderId = orderId;
this.createTime = createTime;
this.price = price;
this.status = status;
this.userId = userId;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
@Override
public String toString() {
return "Order{" +
"orderId='" + orderId + '\'' +
", createTime=" + createTime +
", price=" + price +
", status=" + status +
", userId=" + userId +
'}';
}
}
package top.qaqaq.pojo;
import java.math.BigDecimal;
/**
* @author RichieZhang
* @create 2022-12-14 下午 4:13
*/
public class OrderItem {
private Integer id; //主键编号
private String name; //商品名称
private Integer count; //数量
private BigDecimal price; //单价
private BigDecimal totalPrice; //总价
private String orderId; //订单号
public OrderItem() {
}
public OrderItem(Integer id, String name, Integer count, BigDecimal price, BigDecimal totalPrice, String orderId) {
this.id = id;
this.name = name;
this.count = count;
this.price = price;
this.totalPrice = totalPrice;
this.orderId = orderId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
@Override
public String toString() {
return "OrderItem{" +
"id=" + id +
", name='" + name + '\'' +
", count=" + count +
", price=" + price +
", totalPrice=" + totalPrice +
", orderId='" + orderId + '\'' +
'}';
}
}
2.2.3、编写订单模块的 Dao 程序和测试
OrderDao 接口
package top.qaqaq.dao;
import top.qaqaq.pojo.Order;
/**
* @author RichieZhang
* @create 2022-12-14 下午 4:17
*/
public interface OrderDao {
/**
* 保存订单
* @param order
* @return
*/
public int saveOrder(Order order);
}
OrderDao 实现
package top.qaqaq.dao.impl;
import top.qaqaq.dao.OrderDao;
import top.qaqaq.pojo.Order;
import java.text.SimpleDateFormat;
/**
* @author RichieZhang
* @create 2022-12-14 下午 4:18
*/
public class OrderDaoImpl extends BaseDao implements OrderDao {
@Override
public int saveOrder(Order order) {
String sql = "insert into t_order(order_id,create_time,price,status,user_id) values(?,?,?,?,?)";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return update(sql, order.getOrderId(),sdf.format(order.getCreateTime()),order.getPrice(),order.getStatus(),order.getUserId());
}
}
OrderItemDao 接口
package top.qaqaq.dao;
import top.qaqaq.pojo.OrderItem;
/**
* @author RichieZhang
* @create 2022-12-14 下午 4:17
*/
public interface OrderItemDao {
/**
* 保存订单项
* @param orderItem
* @return
*/
public int saveOrderItem(OrderItem orderItem);
}
OrderItemDao 实现
package top.qaqaq.dao.impl;
import top.qaqaq.dao.OrderItemDao;
import top.qaqaq.pojo.OrderItem;
/**
* @author RichieZhang
* @create 2022-12-14 下午 4:23
*/
public class OrderItemDaoImpl extends BaseDao implements OrderItemDao {
@Override
public int saveOrderItem(OrderItem orderItem) {
String sql = "insert into t_order_item(name,count,price,total_price,order_id) values(?,?,?,?,?)";
return update(sql,orderItem.getName(),orderItem.getCount(),orderItem.getPrice(),orderItem.getTotalPrice(),orderItem.getOrderId());
}
}
测试
package top.qaqaq.test;
import org.junit.Test;
import top.qaqaq.dao.OrderDao;
import top.qaqaq.dao.impl.OrderDaoImpl;
import top.qaqaq.pojo.Order;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author RichieZhang
* @create 2022-12-14 下午 4:28
*/
public class OrderDaoTest {
@Test
public void saveOrder() {
OrderDao orderDao = new OrderDaoImpl();
orderDao.saveOrder(new Order("1234567890",new Date(),new BigDecimal(100),0,1));
}
}
package top.qaqaq.test;
import org.junit.Test;
import top.qaqaq.dao.OrderItemDao;
import top.qaqaq.dao.impl.OrderItemDaoImpl;
import top.qaqaq.pojo.OrderItem;
import java.math.BigDecimal;
import static org.junit.Assert.*;
/**
* @author RichieZhang
* @create 2022-12-14 下午 5:31
*/
public class OrderItemDaoTest {
@Test
public void saveOrderItem() {
OrderItemDao orderItemDao = new OrderItemDaoImpl();
orderItemDao.saveOrderItem(new OrderItem(null,"java从入门到精通",1,new BigDecimal(100),new BigDecimal(100),"1234567890"));
orderItemDao.saveOrderItem(new OrderItem(null,"javaScript从入门到精通",2,new BigDecimal(100),new BigDecimal(200),"1234567890"));
orderItemDao.saveOrderItem(new OrderItem(null,"Netty入门",1,new BigDecimal(100),new BigDecimal(100),"1234567890"));
}
}
2.2.4、编写订单模块的 Service 和测试
package top.qaqaq.service;
import top.qaqaq.pojo.Cart;
/**
* @author RichieZhang
* @create 2022-12-14 下午 5:38
*/
public interface OrderService {
/**
* 生成订单
* @param cart
* @param userId
* @return
*/
public String createOrder(Cart cart,Integer userId);
}
OrderService 实现类
package top.qaqaq.service.impl;
import top.qaqaq.dao.BookDao;
import top.qaqaq.dao.OrderDao;
import top.qaqaq.dao.OrderItemDao;
import top.qaqaq.dao.impl.BookDaoImpl;
import top.qaqaq.dao.impl.OrderDaoImpl;
import top.qaqaq.dao.impl.OrderItemDaoImpl;
import top.qaqaq.pojo.*;
import top.qaqaq.service.OrderService;
import java.util.Date;
import java.util.Map;
/**
* @author RichieZhang
* @create 2022-12-14 下午 5:40
*/
public class OrderServiceImpl implements OrderService {
private OrderDao orderDao = new OrderDaoImpl();
private OrderItemDao orderItemDao = new OrderItemDaoImpl();
private BookDao bookDao = new BookDaoImpl();
@Override
public String createOrder(Cart cart, Integer userId) {
// 订单号===唯一性
String orderId = System.currentTimeMillis() + "" + userId;
// 创建一个订单对象
Order order = new Order(orderId,new Date(),cart.getTotalPrice(),0,userId);
// 保存订单
orderDao.saveOrder(order);
// 遍历购物车中每一个商品项转换成为订单项保存到数据库
for (Map.Entry<Integer, CartItem> entry : cart.getItems().entrySet()) {
// 获取每一个购物车中的商品项
CartItem cartItem = entry.getValue();
// 转换为每一个订单项
OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice(),orderId);
// 保存订单项到书库
orderItemDao.saveOrderItem(orderItem);
// 更新库存和销量
Book book = bookDao.queryBookById(cartItem.getId());
book.setSales(book.getSales() + cartItem.getCount());
book.setStock(book.getStock() - cartItem.getCount());
bookDao.updateBook(book);
}
// 清空购物车
cart.clear();
return orderId;
}
}
测试
package top.qaqaq.test;
import org.junit.Test;
import top.qaqaq.pojo.Cart;
import top.qaqaq.pojo.CartItem;
import top.qaqaq.service.OrderService;
import top.qaqaq.service.impl.OrderServiceImpl;
import java.math.BigDecimal;
/**
* @author RichieZhang
* @create 2022-12-14 下午 6:21
*/
public class OrderServiceTest {
@Test
public void createOrder() {
Cart cart = new Cart();
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(1000),new BigDecimal(1000)));
cart.addItem(new CartItem(2,"数据结构与算法",1,new BigDecimal(100),new BigDecimal(100)));
OrderService orderService = new OrderServiceImpl();
System.out.println("订单号是:" + orderService.createOrder(cart,1));
}
}
2.2.5、编写订单模块的 web 层和页面联调
修改 OrderService 程序:
package top.qaqaq.service.impl;
import top.qaqaq.dao.BookDao;
import top.qaqaq.dao.OrderDao;
import top.qaqaq.dao.OrderItemDao;
import top.qaqaq.dao.impl.BookDaoImpl;
import top.qaqaq.dao.impl.OrderDaoImpl;
import top.qaqaq.dao.impl.OrderItemDaoImpl;
import top.qaqaq.pojo.*;
import top.qaqaq.service.OrderService;
import java.util.Date;
import java.util.Map;
/**
* @author RichieZhang
* @create 2022-12-14 下午 5:40
*/
public class OrderServiceImpl implements OrderService {
private OrderDao orderDao = new OrderDaoImpl();
private OrderItemDao orderItemDao = new OrderItemDaoImpl();
private BookDao bookDao = new BookDaoImpl();
@Override
public String createOrder(Cart cart, Integer userId) {
// 订单号===唯一性
String orderId = System.currentTimeMillis() + "" + userId;
// 创建一个订单对象
Order order = new Order(orderId,new Date(),cart.getTotalPrice(),0,userId);
// 保存订单
orderDao.saveOrder(order);
// 遍历购物车中每一个商品项转换成为订单项保存到数据库
for (Map.Entry<Integer, CartItem> entry : cart.getItems().entrySet()) {
// 获取每一个购物车中的商品项
CartItem cartItem = entry.getValue();
// 转换为每一个订单项
OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice(),orderId);
// 保存订单项到书库
orderItemDao.saveOrderItem(orderItem);
// 更新库存和销量
Book book = bookDao.queryBookById(cartItem.getId());
book.setSales(book.getSales() + cartItem.getCount());
book.setStock(book.getStock() - cartItem.getCount());
bookDao.updateBook(book);
}
// 清空购物车
cart.clear();
return orderId;
}
}
OrderServlet 程序:
package top.qaqaq.web;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.qaqaq.pojo.Cart;
import top.qaqaq.pojo.User;
import top.qaqaq.service.OrderService;
import top.qaqaq.service.impl.OrderServiceImpl;
import java.io.IOException;
/**
* @author RichieZhang
* @create 2022-12-14 下午 6:29
*/
public class OrderServlet extends BaseServlet{
private OrderService orderService = new OrderServiceImpl();
/**
* 生成订单
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void createOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 先获取Cart购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
// 获取Userid
User loginUser = (User) req.getSession().getAttribute("user");
if (loginUser == null) {
req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
return;
}
Integer userId = loginUser.getId();
// 调用orderService.createOrder(Cart,Userid);生成订单
String orderId = orderService.createOrder(cart, userId);
/* req.setAttribute("orderId",orderId);
// 请求转发到/pages/cart/checkout.jsp
req.getRequestDispatcher("/pages/cart/checkout.jsp").forward(req,resp);*/
req.getSession().setAttribute("orderId",orderId);
resp.sendRedirect(req.getContextPath() + "/pages/cart/checkout.jsp");
}
}
修改 pages/cart/cart.jsp 页面,结账的请求地址:
修改 pages/cart/checkout.jsp 页面,输出订单号:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>结算页面</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
<style type="text/css">
h1 {
text-align: center;
margin-top: 200px;
}
</style>
</head>
<body>
<div id="header">
<img class="logo_img" alt="" src="../../static/img/logo.gif" >
<span class="wel_word">结算</span>
<%-- 静态包含,登陆成功之后的菜单 --%>
<%@ include file="/pages/common/login_success_menu.jsp"%>
</div>
<div id="main">
<h1>你的订单已结算,订单号为:${sessionScope.orderId}</h1>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<!-- <servlet>-->
<!-- <servlet-name>RegistServlet</servlet-name>-->
<!-- <servlet-class>top.qaqaq.web.RegistServlet</servlet-class>-->
<!-- </servlet>-->
<!-- <servlet-mapping>-->
<!-- <servlet-name>RegistServlet</servlet-name>-->
<!-- <url-pattern>/registServlet</url-pattern>-->
<!-- </servlet-mapping>-->
<!-- <servlet>-->
<!-- <servlet-name>LoginServlet</servlet-name>-->
<!-- <servlet-class>top.qaqaq.web.LoginServlet</servlet-class>-->
<!-- </servlet>-->
<!-- <servlet-mapping>-->
<!-- <servlet-name>LoginServlet</servlet-name>-->
<!-- <url-pattern>/loginServlet</url-pattern>-->
<!-- </servlet-mapping>-->
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>top.qaqaq.web.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>BookServlet</servlet-name>
<servlet-class>top.qaqaq.web.BookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>BookServlet</servlet-name>
<url-pattern>/manager/bookServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ClientBookServlet</servlet-name>
<servlet-class>top.qaqaq.web.ClientBookServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ClientBookServlet</servlet-name>
<url-pattern>/client/bookServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>top.qaqaq.web.MyKaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>CartServlet</servlet-name>
<servlet-class>top.qaqaq.web.CartServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CartServlet</servlet-name>
<url-pattern>/cartServlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>OrderServlet</servlet-name>
<servlet-class>top.qaqaq.web.OrderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>OrderServlet</servlet-name>
<url-pattern>/orderServlet</url-pattern>
</servlet-mapping>
</web-app>