D16 Sping Boot 入门 Sping框架--Java Web之书城项目(七) 订单模块
一、订单模块分析
二、订单模块的实现
①、创建订单模块的数据库表
1 use book; 2 3 create table t_order( 4 `order_id` varchar(50) primary key, 5 `create_time` datetime, 6 `price` decimal(11,2), 7 `status` int, 8 `user_id` int, 9 foreign key(`user_id`) references t_user(`id`) 10 ); 11 12 13 create table t_order_item( 14 `id` int primary key auto_increment, 15 `name` varchar(100), 16 `count` int, 17 `price` decimal(11,2), 18 `total_price` decimal(11,2), 19 `order_id` varchar(50), 20 foreign key(`order_id`) references t_order(`order_id`) 21 );
②、创建订单模块的数据模型(订单和订单项)
在pojo里创建Order类和OrderItem类
1 package com.gychen.pojo; 2 3 import java.math.BigDecimal; 4 import java.util.Date; 5 6 public class Order { 7 8 private String orderId; 9 private Date createTime; 10 private BigDecimal price; 11 //0未发货,1已发货,2已签收 12 private Integer status = 0; 13 private Integer userId; 14 15 public String getOrderId() { 16 return orderId; 17 } 18 19 public void setOrderId(String orderId) { 20 this.orderId = orderId; 21 } 22 23 public Date getCreateTime() { 24 return createTime; 25 } 26 27 public void setCreateTime(Date createTime) { 28 this.createTime = createTime; 29 } 30 31 public BigDecimal getPrice() { 32 return price; 33 } 34 35 public void setPrice(BigDecimal price) { 36 this.price = price; 37 } 38 39 public Integer getStatus() { 40 return status; 41 } 42 43 public void setStatus(Integer status) { 44 this.status = status; 45 } 46 47 public Integer getUserId() { 48 return userId; 49 } 50 51 public void setUserId(Integer userId) { 52 this.userId = userId; 53 } 54 55 @Override 56 public String toString() { 57 return "Order{" + 58 "orderId='" + orderId + '\'' + 59 ", createTime=" + createTime + 60 ", price=" + price + 61 ", status=" + status + 62 ", userId=" + userId + 63 '}'; 64 } 65 66 public Order(String orderId, Date createTime, BigDecimal price, Integer status, Integer userId) { 67 this.orderId = orderId; 68 this.createTime = createTime; 69 this.price = price; 70 this.status = status; 71 this.userId = userId; 72 } 73 74 public Order() { 75 } 76 }
1 package com.gychen.pojo; 2 3 import java.math.BigDecimal; 4 5 public class OrderItem { 6 7 private Integer id; 8 private String name; 9 private Integer count; 10 private BigDecimal price; 11 private BigDecimal totalPrice; 12 private String orderId; 13 14 public Integer getId() { 15 return id; 16 } 17 18 public void setId(Integer id) { 19 this.id = id; 20 } 21 22 public String getName() { 23 return name; 24 } 25 26 public void setName(String name) { 27 this.name = name; 28 } 29 30 public Integer getCount() { 31 return count; 32 } 33 34 public void setCount(Integer count) { 35 this.count = count; 36 } 37 38 public BigDecimal getPrice() { 39 return price; 40 } 41 42 public void setPrice(BigDecimal price) { 43 this.price = price; 44 } 45 46 public BigDecimal getTotalPrice() { 47 return totalPrice; 48 } 49 50 public void setTotalPrice(BigDecimal totalPrice) { 51 this.totalPrice = totalPrice; 52 } 53 54 public String getOrderId() { 55 return orderId; 56 } 57 58 public void setOrderId(String orderId) { 59 this.orderId = orderId; 60 } 61 62 public OrderItem(Integer id, String name, Integer count, BigDecimal price, BigDecimal totalPrice, String orderId) { 63 this.id = id; 64 this.name = name; 65 this.count = count; 66 this.price = price; 67 this.totalPrice = totalPrice; 68 this.orderId = orderId; 69 } 70 71 public OrderItem() { 72 } 73 74 @Override 75 public String toString() { 76 return "OrderItem{" + 77 "id=" + id + 78 ", name='" + name + '\'' + 79 ", count=" + count + 80 ", price=" + price + 81 ", totalPrice=" + totalPrice + 82 ", orderId='" + orderId + '\'' + 83 '}'; 84 } 85 }
③、编写订单模块的Dao程序和测试
在dao里创建OrderDao、OrderItemDao接口和OrderDaoImpl、OrderItemDaoImpl实现类
1 package com.gychen.dao; 2 3 import com.gychen.pojo.Order; 4 5 public interface OrderDao { 6 7 public int saveOrder(Order order); 8 }
1 package com.gychen.dao; 2 3 import com.gychen.pojo.OrderItem; 4 5 public interface OrderItemDao { 6 7 public int saveOrderItem(OrderItem orderItem); 8 }
1 package com.gychen.dao.impl; 2 3 import com.gychen.dao.OrderDao; 4 import com.gychen.pojo.Order; 5 6 public class OrderDaoImpl extends BaseDao implements OrderDao { 7 8 @Override 9 public int saveOrder(Order order) { 10 String sql = "insert into t_order(`order_id`,`create_time`,`price`,`status`,`user_id`) values(?,?,?,?,?)"; 11 12 return update(sql,order.getOrderId(),order.getCreateTime(),order.getPrice(),order.getStatus(),order.getUserId()); 13 } 14 }
1 package com.gychen.dao.impl; 2 3 import com.gychen.dao.OrderItemDao; 4 import com.gychen.pojo.OrderItem; 5 6 public class OrderItemDaoImpl extends BaseDao implements OrderItemDao { 7 8 @Override 9 public int saveOrderItem(OrderItem orderItem) { 10 String sql = "insert into t_order_item(`name`,`count`,`price`,`total_price`,`order_id`) values(?,?,?,?,?)"; 11 return update(sql, orderItem.getName(),orderItem.getCount(), 12 orderItem.getPrice(),orderItem.getTotalPrice(),orderItem.getOrderId()); 13 } 14 }
在test里创建测试类(在实现类中ctr+shift+t)
1 package com.gychen.test; 2 3 import com.gychen.dao.OrderDao; 4 import com.gychen.dao.impl.OrderDaoImpl; 5 import com.gychen.pojo.Order; 6 import org.junit.Test; 7 8 import java.math.BigDecimal; 9 import java.util.Date; 10 11 import static org.junit.Assert.*; 12 13 public class OrderDaoImplTest { 14 15 @Test 16 public void saveOrder() { 17 OrderDao orderDao = new OrderDaoImpl(); 18 19 orderDao.saveOrder(new Order("1234567890",new Date(),new BigDecimal(100),0,1)); 20 } 21 }
1 package com.gychen.test; 2 3 import com.gychen.dao.OrderItemDao; 4 import com.gychen.dao.impl.OrderItemDaoImpl; 5 import com.gychen.pojo.OrderItem; 6 import org.junit.Test; 7 8 import java.math.BigDecimal; 9 10 import static org.junit.Assert.*; 11 12 public class OrderItemDaoImplTest { 13 14 @Test 15 public void saveOrderItem() { 16 17 OrderItemDao orderItemDao = new OrderItemDaoImpl(); 18 19 orderItemDao.saveOrderItem(new OrderItem(null,"java从入门到精通", 20 1, new BigDecimal(50),new BigDecimal(50),"1234567890")); 21 orderItemDao.saveOrderItem(new OrderItem(null,"javaScript从入门到精通", 22 2, new BigDecimal(50),new BigDecimal(100),"1234567890")); 23 orderItemDao.saveOrderItem(new OrderItem(null,"Netty入门", 24 1, new BigDecimal(100),new BigDecimal(100),"1234567890")); 25 26 } 27 }
③、编写订单模块的Service和测试
在service中新建OrderService接口、实现类和测试
1 package com.gychen.service; 2 3 import com.gychen.pojo.Cart; 4 5 public interface OrderService { 6 7 public String createOrder(Cart cart, Integer userId); 8 9 10 }
1 package com.gychen.service.impl; 2 3 import com.gychen.dao.OrderDao; 4 import com.gychen.dao.OrderItemDao; 5 import com.gychen.dao.impl.OrderDaoImpl; 6 import com.gychen.dao.impl.OrderItemDaoImpl; 7 import com.gychen.pojo.Cart; 8 import com.gychen.pojo.CartItem; 9 import com.gychen.pojo.Order; 10 import com.gychen.pojo.OrderItem; 11 import com.gychen.service.OrderService; 12 13 import java.util.Date; 14 import java.util.Map; 15 16 public class OrderServiceImpl implements OrderService { 17 18 private OrderDao orderDao = new OrderDaoImpl(); 19 private OrderItemDao orderItemDao = new OrderItemDaoImpl(); 20 21 @Override 22 public String createOrder(Cart cart, Integer userId) { 23 // 订单号唯一 时间戳+用户id 24 String orderId = System.currentTimeMillis()+""+userId; 25 // 创建一个订单对象 26 Order order = new Order(orderId,new Date(), cart.getTotalPrice(),0,userId); 27 // 保存订单 28 orderDao.saveOrder(order); 29 // 遍历购物车中每一个商品项,转换成为订单项保存到数据库 30 for (Map.Entry<Integer, CartItem>entry : cart.getItems().entrySet()){ 31 // 获取每一各购物车中的商品项 32 CartItem cartItem = entry.getValue(); 33 // 转换为每一个订单项 34 OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(), 35 cartItem.getPrice(),cartItem.getTotalPrice(),orderId); 36 // 保存订单项到数据库 37 orderItemDao.saveOrderItem(orderItem); 38 } 39 // 清空购物车 40 cart.clear(); 41 return orderId; 42 } 43 }
1 package com.gychen.test; 2 3 import com.gychen.pojo.Cart; 4 import com.gychen.pojo.CartItem; 5 import com.gychen.service.OrderService; 6 import com.gychen.service.impl.OrderServiceImpl; 7 import org.junit.Test; 8 9 import java.math.BigDecimal; 10 11 import static org.junit.Assert.*; 12 13 public class OrderServiceImplTest { 14 15 @Test 16 public void createOrder() { 17 18 Cart cart = new Cart(); 19 cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(200),new BigDecimal(200))); 20 cart.addItem(new CartItem(2,"python从入门到精通",1,new BigDecimal(100),new BigDecimal(100))); 21 cart.addItem(new CartItem(1,"java从入门到精通",1,new BigDecimal(200),new BigDecimal(200))); 22 OrderService orderService = new OrderServiceImpl(); 23 System.out.println("订单号是:"+orderService.createOrder(cart,1)); 24 } 25 }
④、编写订单模块的web层OrderServlet并在web.xml里配置路径
1 package com.gychen.web; 2 3 import com.gychen.pojo.Cart; 4 import com.gychen.pojo.User; 5 import com.gychen.service.OrderService; 6 import com.gychen.service.impl.OrderServiceImpl; 7 8 import javax.servlet.ServletException; 9 import javax.servlet.http.HttpServletRequest; 10 import javax.servlet.http.HttpServletResponse; 11 import java.io.IOException; 12 13 public class OrderServlet extends BaseServlet { 14 15 private OrderService orderService = new OrderServiceImpl(); 16 /** 17 * 生成订单 18 * @param req 请求 19 * @param resp 响应 20 * @throws ServletException 21 * @throws IOException 22 */ 23 protected void createOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 24 // 先获取Cart购物车对象 25 Cart cart = (Cart) req.getSession().getAttribute("cart"); 26 // 获取userId 27 User loginUser = (User) req.getSession().getAttribute("user"); 28 // 判断用户是否登录 29 if (loginUser == null){ 30 req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp); 31 return; 32 } 33 Integer userId = loginUser.getId(); 34 35 // 调用OrderService.createOrder(Cart,userId)生成订单 36 String orderId = orderService.createOrder(cart,userId); 37 38 // req.setAttribute("orderId",orderId); 39 req.getSession().setAttribute("orderId",orderId); 40 // 请求转发到/pages/cart/checkout.jsp 41 // req.getRequestDispatcher("/pages/cart/checkout.jsp").forward(req,resp); 42 // 防止重复提交 43 resp.sendRedirect(req.getContextPath()+"/pages/cart/checkout.jsp"); 44 } 45 }
在OrderServiceImpl里添加更新库存和销量功能
1 package com.gychen.service.impl; 2 3 import com.gychen.dao.BookDao; 4 import com.gychen.dao.OrderDao; 5 import com.gychen.dao.OrderItemDao; 6 import com.gychen.dao.impl.BookDaoImpl; 7 import com.gychen.dao.impl.OrderDaoImpl; 8 import com.gychen.dao.impl.OrderItemDaoImpl; 9 import com.gychen.pojo.*; 10 import com.gychen.service.OrderService; 11 12 import java.util.Date; 13 import java.util.Map; 14 15 public class OrderServiceImpl implements OrderService { 16 17 private OrderDao orderDao = new OrderDaoImpl(); 18 private OrderItemDao orderItemDao = new OrderItemDaoImpl(); 19 private BookDao bookDao = new BookDaoImpl(); 20 21 @Override 22 public String createOrder(Cart cart, Integer userId) { 23 // 订单号唯一 时间戳+用户id 24 String orderId = System.currentTimeMillis()+""+userId; 25 // 创建一个订单对象 26 Order order = new Order(orderId,new Date(), cart.getTotalPrice(),0,userId); 27 // 保存订单 28 orderDao.saveOrder(order); 29 // 遍历购物车中每一个商品项,转换成为订单项保存到数据库 30 for (Map.Entry<Integer, CartItem>entry : cart.getItems().entrySet()){ 31 // 获取每一各购物车中的商品项 32 CartItem cartItem = entry.getValue(); 33 // 转换为每一个订单项 34 OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(), 35 cartItem.getPrice(),cartItem.getTotalPrice(),orderId); 36 // 保存订单项到数据库 37 orderItemDao.saveOrderItem(orderItem); 38 39 // 更新库存和销量 40 Book book = bookDao.queryBookById(cartItem.getId()); 41 book.setSales(book.getSales()+cartItem.getCount()); 42 book.setStock(book.getStock()-cartItem.getCount()); 43 bookDao.updateBook(book); 44 } 45 // 清空购物车 46 cart.clear(); 47 return orderId; 48 } 49 }
<%@ 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> <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:forEach items="${sessionScope.cart.items}" var="entry"> <tr> <td>${entry.value.name}</td> <td> <input class="updateCount" type="text" value="${entry.value.count}" bookId="${entry.value.id}" style="width: 60px;" onkeyup="(this.v=function(){this.value=this.value.replace(/[^0-9-]+/,'');}).call(this)" onblur="this.v();"> </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 test="${empty sessionScope.cart.items}"> <tr> <td colspan="5"><a href="${pageScope.basePath}index.jsp">亲,当前购物车为空,快去浏览吧。</a></td> </tr> </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 class="clearCart" href="cartServlet?action=clearCart">清空购物车</a></span> <span class="cart_span"><a href="orderServlet?action=createOrder">去结账</a></span> </div> </c:if> </div> <%--静态包含页脚内容--%> <%@include file="/pages/common/footer.jsp"%> <script> $(function () { //删除购物车商品事件 $("a.deleteItem").click(function () { return confirm("您确定要删除【"+$(this).parent().parent().find("td:first").text()+"】吗?") }); //清空购物车事件 $("a.clearCart").click(function () { return confirm("您确定要清空购物车吗?") }); //修改购物车商品数量事件 $(".updateCount").change(function () { var name = $(this).parent().parent().find("td:first").text(); var count = this.value; var bookId = $(this).attr("bookId"); if (confirm("您确定要将【"+name+"】的数量修改为【"+count+"】吗?")){ //发起请求给服务器保存修改 location.href = "${pageScope.basePath}cartServlet?action=updateCount&count="+count+"&id="+bookId; } else { //defauleValue 是表单DOM默认值,即原来表单的值 this.value = this.defaultValue; } }); }); </script> </body> </html>
1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <!DOCTYPE html> 3 <html> 4 <head> 5 <meta charset="UTF-8"> 6 <title>结算页面</title> 7 <%-- 静态包含 base标签、css样式、jQuery文件 --%> 8 <%@ include file="/pages/common/head.jsp"%> 9 <style type="text/css"> 10 h1 { 11 text-align: center; 12 margin-top: 200px; 13 } 14 </style> 15 </head> 16 <body> 17 18 <div id="header"> 19 <img class="logo_img" alt="" src="../../static/img/logo.gif" > 20 <span class="wel_word">结算</span> 21 <%@include file="/pages/common/login_success_menu.jsp"%> 22 </div> 23 24 <div id="main"> 25 26 <h1>你的订单已结算,订单号为: ${sessionScope.orderId}</h1> 27 28 29 </div> 30 31 <%--静态包含页脚内容--%> 32 <%@include file="/pages/common/footer.jsp"%> 33 </body> 34 </html>