购物车和订单
前言
购物车和订单的Session版,部分代码如下,包含核心思想。
一、购物车实现
1、Core思想
2、CartServlet(Session版)
package com.xhu.web;
import com.xhu.pojo.Book;
import com.xhu.pojo.Cart;
import com.xhu.pojo.CartItem;
import com.xhu.service.BookService;
import com.xhu.service.impl.BookServiceImpl;
import com.xhu.utils.ParseUtil;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CartServlet extends BaseServlet {
private BookService bs = new BookServiceImpl();
/**
* 加入购物车
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取商品编号
int id = ParseUtil.parseString(req.getParameter("id"), 0);
//2.通过编号获取图书信息
Book book = bs.getBookById(id);
//3.把图书信息转化未CartItem对象
if (book != null) {
CartItem c = new CartItem(book.getId(), book.getName(), 1, book.getPrice());
//4.添加CartItem对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if (cart == null)
cart = new Cart();
cart.addItem(c);
req.getSession().setAttribute("cart", cart);
req.getSession().setAttribute("lastItem",c.getName());
}
//5.重定向到商品列表页面,回到原来的地址,该地址会随请求头一起过来,即referer
resp.sendRedirect(req.getHeader("referer"));
}
/**
* 删除商品
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void deleteItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取cart对象以及要删除的id
int id = ParseUtil.parseString(req.getParameter("id"), 0);
Cart cart = (Cart) req.getSession().getAttribute("cart");
//2.移除cart中该id的商品
if (cart != null) cart.deleteItem(id);
//3.重定向到购物车
resp.sendRedirect(req.getHeader("referer"));
}
/**
* 清空商品
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
protected void clear(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.将购物车直接remove
req.getSession().removeAttribute("cart");
//2.重定向到首页
resp.sendRedirect(req.getContextPath() + "/index.jsp");
}
protected void updateCount(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1.获取商品id和数量
int id = ParseUtil.parseString(req.getParameter("id"), 0);
int count = ParseUtil.parseString(req.getParameter("count"), 1);
//2.获取对应id的商品对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
//3.修改数量
if (cart != null)
cart.updateCount(id, count);
//4.重定向回去
resp.sendRedirect(req.getHeader("referer"));
}
}
3、对Cart建模
package com.xhu.pojo;
import java.math.BigDecimal;
import java.util.*;
/**
* 对购物车进行建模
*/
public class Cart {
//private Integer totalCount = 0;
//private BigDecimal totalPrice = new BigDecimal(0);
private Map<Integer, CartItem> items = new LinkedHashMap<>();
public Cart() {
}
public Integer getTotalCount() {
int totalCount = 0;
for (CartItem value : items.values()) {
totalCount += value.getCount();
}
return totalCount;
}
public BigDecimal getTotalPrice() {
BigDecimal totalPrice = new BigDecimal(0);
for (CartItem value : items.values()) {
totalPrice = totalPrice.add(value.getTotalPrice());
}
return totalPrice;
}
public Map<Integer, CartItem> getItems() {
return items;
}
@Override
public String toString() {
return "Cart{" +
"totalCount=" + getTotalCount() +
", totalPrice=" + getTotalPrice() +
", items=" + Arrays.toString(items.entrySet().toArray()) +
'}';
}
/**
* 添加商品项
*
* @param cartItem
*/
public void addItem(CartItem cartItem) {
//查找商品是否存在,若存在,则数量+1,总金额增加;如果不存在则添加在后面就可以了。
CartItem c = items.get(cartItem.getId());
if (c != null) {
//修改变化的源头,即该item数量+1
c.setCount(c.getCount() + 1);
return;
}
items.put(cartItem.getId(), cartItem);
}
/**
* 删除商品项
*
* @param id
*/
public void deleteItem(Integer id) {
//直接修改源头,将该商品删掉就行
items.remove(id);
}
/**
* 清空购物车
*/
public void clear() {
items.clear();
}
/**
* 修改商品数量
*
* @param id
* @param count
*/
public void updateCount(Integer id, Integer count) {
//查看是否有该商品,有才修改。
CartItem c = items.get(id);
if (c != null) {
//修改变化的源头,即该item数量+1
c.setCount(count <= 0 ? 0 : count >= 10000 ? 10000 : count);
return;
}
}
}
4、Cart建模中所需的CartItem
package com.xhu.pojo;
import java.math.BigDecimal;
/**
* 对购物车商品项建模
*/
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) {
this.id = id;
this.name = name;
this.count = count;
this.price = price;
}
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 getPrice().multiply(new BigDecimal(getCount()));
}
@Override
public String toString() {
return "CartItem{" +
"id=" + id +
", name='" + name + '\'' +
", count=" + count +
", price=" + price +
", totalPrice=" + getTotalPrice() +
'}';
}
}
二、联合订单
1、创建订单
protected void saveOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
User user = (User) session.getAttribute("user");
if (user == null) {
resp.sendRedirect(req.getContextPath() + "/pages/user/login.jsp");
return;
}
Cart cart = (Cart) session.getAttribute("cart");
if (cart == null) {
resp.sendRedirect(req.getContextPath() + "/index.jsp");
return;
}
String orderId = os.createOrder(cart, user.getId());
if (orderId != null) {
session.removeAttribute("cart");
session.setAttribute("orderId", orderId);
}else session.setAttribute("errorMsg","商品被抢光了");
//避免表单重复提交,重构向到checkout.jsp
resp.sendRedirect(req.getContextPath() + "/pages/cart/checkout.jsp");
}
2、Service层
package com.xhu.service.impl;
import com.xhu.dao.BookDAO;
import com.xhu.dao.OrderDAO;
import com.xhu.dao.OrderItemDAO;
import com.xhu.dao.impl.BookDAOImpl;
import com.xhu.dao.impl.OrderDAOImpl;
import com.xhu.dao.impl.OrderItemDAOImpl;
import com.xhu.pojo.Cart;
import com.xhu.pojo.CartItem;
import com.xhu.pojo.Order;
import com.xhu.pojo.OrderItem;
import com.xhu.service.BookService;
import com.xhu.service.OrderService;
import com.xhu.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
public class OrderServiceImpl implements OrderService {
private OrderDAO od = new OrderDAOImpl();
private OrderItemDAO oid = new OrderItemDAOImpl();
private BookDAO bd = new BookDAOImpl();
private Connection conn;
@Override
public String createOrder(Cart cart, int userId) {
conn = JDBCUtils.getConn();
try {
conn.setAutoCommit(false);
//1.保存订单
Date date = new Date(Calendar.getInstance().getTime().getTime());
String orderId = new StringBuilder().append(System.currentTimeMillis()).append(userId).toString();
Order order = new Order(orderId, date, cart.getTotalPrice(), userId);
od.saveOrder(conn, order);
//2.保存订单项
Map<Integer, CartItem> items = cart.getItems();
//无则返回
if (items == null || items.values().size() == 0) {
conn.rollback();
return null;
}
//有则进行迭代添加
Iterator<CartItem> iterator = items.values().iterator();
CartItem next = null;
String orderItemId = null;
OrderItem oi = null;
boolean flag = true;
while (iterator.hasNext()) {
next = iterator.next();
System.out.println(next);
orderItemId = new StringBuilder().append(System.currentTimeMillis()).append(userId).toString();
oi = new OrderItem(orderItemId, next.getName(), next.getPrice(), next.getCount(), orderId);
flag = oid.saveOrderItem(conn, oi) > 0;
//判断商品是否被抢光
flag &= bd.updateCountById(conn, next.getId(),next.getCount()) > 0;
if (!flag) {
conn.rollback();
return null;
}
}
//3.提交事务并返回true
conn.commit();
return orderId;
} catch (SQLException throwables) {
try {
//异常rollback
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}
JDBCUtils.close(conn);
return null;
}
}
3、更新图书销量和库存
@Override
public int updateCountById(Connection conn, int id, int count) throws SQLException {
String sql = "update book set stock = stock - ?,sales = sales + ? where id = ? and stock - ? >= 0";
return update(conn, sql, count, count, id, count);
}
总结
1)打好面向对象的基础,代码不是关键,core在于对于需求建模,并拆分业务,最后再写好每一层逻辑。(MVC思想+三层结构解耦)
2)Base Step,
Mining demand -> Modeling demand -> Creating table for model -> POJO -> DAO -> Service -> Servlet -> JSP
参考文献
[1] JavaWeb 尚硅谷