购物车概述
购物车的设计
- 基于 Session 的购物车
购物车是存储到 Session 作用域的,浏览器关闭购物车就没有了 - 基于 Cookie 的购物车
和基于 Session 一样,内容存在浏览器中,不能在不同电脑上共享信息 - 基于 Cookie + 数据库 的购物车
购买商品时,如果还没有登录,此时就临时存到 Cookie 中
若已经登录,先读取 Cookie 中的数据,然后保存到数据库中(可以在任何地方查看数据库中信息)
购物车模型和对象的建立
流程大致如下:
CartItem.java:
//购物车中的商品对象
@Data
public class CartItem {
private String id;
private String name;//商品名称
private BigDecimal price;//单价
private Integer num;//购买数量
}
ShoppingCart.java:
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//购物车对象
public class ShoppingCart {
//购物车中的多个商品对象
private List<CartItem> items = new ArrayList<>();
//购物车总价
private BigDecimal totalPrice;
//把商品添加进购物车
public void save(CartItem newItem) {
for (CartItem item : items) {
//如果该商品已经在购物车里,则增加数量
if (item.getId().equals(newItem.getId())) {
item.setNum(item.getNum() + newItem.getNum());
return;
}
}
items.add(newItem);
}
//从购物车中移除指定id的商品
public void delete(String id) {
Iterator<CartItem> it = items.iterator();
while (it.hasNext()) {
CartItem item = it.next();
if (item.getId().equals(id)) {
//items.remove(item);//错误,防止并发修改
it.remove();
break;
}
}
}
//购物车中所有的商品
public List<CartItem> getItem() {
return items;
}
//购物车总价
public BigDecimal getTotalPrice() {
BigDecimal totalPrice = BigDecimal.ZERO;
for (CartItem item : items) {
totalPrice = totalPrice.add(item.getPrice().multiply(new BigDecimal(item.getNum())));
}
return totalPrice;
}
}
购物车的实现
首先写 Servlet 请求:
ShoppingCartServlet.java:
import java.io.IOException;
import java.math.BigDecimal;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.cherry._02_shoppingcart.domain.CartItem;
import com.cherry._02_shoppingcart.domain.ShoppingCart;
//处理购物车的添加删除操作
@WebServlet("/shoppingcart")
public class ShoppingCartServlet extends HttpServlet {
private static final long serialVersionUID = -5568788051811437779L;
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String cmd = req.getParameter("cmd");
if ("save".equals(cmd)) {
this.save(req, resp);
} else if ("delete".equals(cmd)) {
this.delete(req, resp);
}
resp.sendRedirect("/shoppingcart/cart_list.jsp");
}
protected void save(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//1.接收请求参数
String name = req.getParameter("name");
String num = req.getParameter("num");
String id = "";
BigDecimal price = BigDecimal.ZERO;
//写死了编号和单价
if ("iPhone 11".equals(name)) {
id = "11";
price = new BigDecimal("5000");
} else if ("iPhone 11 Pro".equals(name)) {
id = "22";
price = new BigDecimal("8000");
} else if ("iPhone 11 Pro Max".equals(name)) {
id = "33";
price = new BigDecimal("11000");
}
CartItem item = new CartItem(id, name, price, Integer.valueOf(num));
//2.调用业务方法
ShoppingCart cart = (ShoppingCart) req.getSession().getAttribute("SHOPPINGCART_IN_SESSION");
System.out.println(cart);
if (cart == null) {
cart = new ShoppingCart();
req.getSession().setAttribute("SHOPPINGCART_IN_SESSION", cart);
}
cart.save(item);
System.out.println(cart);
//3.控制界面跳转
}
protected void delete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//1.接收请求参数
String id = req.getParameter("id");
//2.调用业务方法
ShoppingCart cart = (ShoppingCart) req.getSession().getAttribute("SHOPPINGCART_IN_SESSION");
cart.delete(id);
//3.控制界面跳转
}
}
这里简单起见就先将商品的单价和编号写死了,实际上应该是通过数据库进行获取。
然后写 JSP 页面:
cart_list.jsp:
package com.cherry._02_shoppingcart.servlet;
import java.io.IOException;
import java.math.BigDecimal;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.cherry._02_shoppingcart.domain.CartItem;
import com.cherry._02_shoppingcart.domain.ShoppingCart;
//处理购物车的添加删除操作
@WebServlet("/shoppingcart")
public class ShoppingCartServlet extends HttpServlet {
private static final long serialVersionUID = -5568788051811437779L;
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String cmd = req.getParameter("cmd");
if ("save".equals(cmd)) {
this.save(req, resp);
} else if ("delete".equals(cmd)) {
this.delete(req, resp);
}
resp.sendRedirect("/shoppingcart/cart_list.jsp");
}
protected void save(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//1.接收请求参数
String name = req.getParameter("name");
String num = req.getParameter("num");
String id = "";
BigDecimal price = BigDecimal.ZERO;
if ("iPhone 11".equals(name)) {
id = "11";
price = new BigDecimal("5000");
} else if ("iPhone 11 Pro".equals(name)) {
id = "22";
price = new BigDecimal("8000");
} else if ("iPhone 11 Pro Max".equals(name)) {
id = "33";
price = new BigDecimal("11000");
}
CartItem item = new CartItem(id, name, price, Integer.valueOf(num));
//2.调用业务方法
ShoppingCart cart = (ShoppingCart) req.getSession().getAttribute("SHOPPINGCART_IN_SESSION");
System.out.println(cart);
if (cart == null) {
cart = new ShoppingCart();
req.getSession().setAttribute("SHOPPINGCART_IN_SESSION", cart);
}
cart.save(item);
System.out.println(cart);
//3.控制界面跳转
}
protected void delete(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//1.接收请求参数
String id = req.getParameter("id");
//2.调用业务方法
ShoppingCart cart = (ShoppingCart) req.getSession().getAttribute("SHOPPINGCART_IN_SESSION");
cart.delete(id);
//3.控制界面跳转
}
}
product_list.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/shoppingcart?cmd=save" method="POST">
商品名称:
<select name="name">
<option>iPhone 11</option>
<option>iPhone 11 Pro</option>
<option>iPhone 11 Pro Max</option>
</select></br>
购买数量:<input type="number" name="num" min="1"}/>
<br/><input type="submit" value="添加进购物车"/>
</form>
</body>
</html>
其中在 JSP 获取作用域对象的属性时,默认调用 getter 方法,因此要么用 lombok 插件生成 Getter Setter 要么自己写,但是一定是 getXxxx(属性名) 不能写错,否则会报找不到属性的异常。我就是 items 的 get 方法写成了 getItem 找了半天的错误,应该写成 getItems。
最终的结果虽然比较丑,但是基本功能都能实现: