效果图
有订单时的效果图
无订单时的效果图
订单详情页
功能
- 生成订单
- 订单页的展示
- 查看订单详情
正文
说明
和购物车同样的,首先得知道我们的订单对应的哪个实体对象。一个用户可能有多条订单记录,一个订单里边可以包含多个
商品(也可以理解为多个购物项)
。理清这个逻辑之后,我们就可以得到两个实体:
订单实体类
和
详细的订单项
对应到界面上就是如下图:
order.jsp(订单页)
<%@ page import="com.service.OrderService"%><%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%><%@ page import="com.myUtil.ProcessUtil"%><%@ page import="com.entity.Order"%><%@ page import="java.util.List"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%--Created by IntelliJIDEA.
User: huawei
Date:2022/10/22Time:20:02To change this template use File|Settings|FileTemplates.--%><%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><title>我的订单</title><!-- 新 Bootstrap5 核心 CSS 文件 --><link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css"><%--icon图标--%><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css"><!-- popper.min.js 用于弹窗、提示、下拉菜单 --><script src="https://cdn.staticfile.org/popper.js/2.9.3/umd/popper.min.js"></script><!-- 最新的 Bootstrap5 核心 JavaScript 文件 --><script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.min.js"></script><script type="text/javascript" src="script/jquery-3.6.0.min.js"></script></head><body><%OrderService orderService =newOrderService();String userId =ProcessUtil.getUserIdBySessionId(session);List<Order> orderList= orderService.showAllOrder(userId);if(orderList!=null&& orderList.size()!=0){
session.setAttribute("orderList",orderList);}%><nav class="navbar-expand-lg navbar navbar-dark bg-primary"><div class="container-fluid "><a class="navbar-brand" href="#">我的订单</a><button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNavDropdown"><ul class="navbar-nav"><li class="nav-item"><a class="nav-link active" aria-current="page" href="/MyProject/index.jsp">Home</a></li></ul></div></div></nav><c:if test="${empty sessionScope.orderList}"><div class="container"><div class="card position-relative" style="margin: 50px;height: 280px;background: #ffffff url(img/CartBackground.png) no-repeat; background-position: center left;"><div class="position-absolute top-50 start-50 translate-middle"><h7>
您还未购买过任何商品哦!赶紧行动吧!您可以:
</h7><br><a class="btn btn-primary btn-lg" href="/MyProject/index.jsp">购物</a></div></div></div></c:if><c:if test="${!empty sessionScope.orderList}"><div class="container"><div class="card"><table class="table table-hover text-center"><tr><td>订单号</td><td>下单时间</td><td>总价</td><td>状态</td><td>详情</td></tr><c:forEach items="${sessionScope.orderList}"var="order"><tr style="vertical-align: middle !important;text-align: center;"><td><%--<img style="width: 100px;height: 100px" src="${or}"/>--%><span>${order.id}</span></td><td><%--分割下单时间--%><c:set value="${fn:split(order.create_time,'T')}"var="time"></c:set><c:forEach var="tm" items="${time}">
${tm}</c:forEach></td><td>${order.price}</td><td>0</td><td><a type="submit"class="btn btn-danger" href="/MyProject/orderDetail.jsp?orderId=${order.id}">查看</a></td></tr></c:forEach></table><div class="row justify-content-between"></div></div></div></c:if></body></html>
订单的展示
这里通过在jsp页面,调用
service层
的
showAllOrder()
来获取所有的订单列表。然后通过
for-Each
来将列表的每条信息渲染到前端页面
订单的查看
和前面几节讲的
留言删除
、
删除购物项
思路一样,通过携带
唯一标识ID(下单时间的毫秒数)
来查看对应订单的详细信息。因为查看订单详情需要跳转页面,所有我们这里采用
<a></a>标签
来进行跳转。相关代码:
<td><atype="submit"class="btn btn-danger"href="/MyProject/orderDetail.jsp?orderId=${order.id}">查看</a></td>
orderDetail.jsp(订单详情页)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@ page import="com.entity.OrderItem"%><%@ page import="com.service.OrderItemService"%><%@ page import="java.util.List"%><%@ page import="com.service.OrderService"%><%@ page import="com.myUtil.ProcessUtil"%><%--Created by IntelliJIDEA.
User: huawei
Date:2022/10/22Time:22:40To change this template use File|Settings|FileTemplates.--%><%@ page contentType="text/html;charset=UTF-8" language="java"%><html><head><title>订单详情页</title><!-- 新 Bootstrap5 核心 CSS 文件 --><link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css"><%--icon图标--%><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css"><!-- popper.min.js 用于弹窗、提示、下拉菜单 --><script src="https://cdn.staticfile.org/popper.js/2.9.3/umd/popper.min.js"></script><!-- 最新的 Bootstrap5 核心 JavaScript 文件 --><script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.min.js"></script><script type="text/javascript" src="script/jquery-3.6.0.min.js"></script></head><body><%OrderItemService orderItemService =newOrderItemService();// String orderId = (String)session.getAttribute("orderId");// if (orderId==null){// 当用户重新登录之后/重启服务器,seesion域中会清空orderId。所以需要String orderId = request.getParameter("orderId");// }List<OrderItem> orderItems = orderItemService.showAllOrderItem(orderId);if(orderItems !=null&& orderItems.size()!=0){
session.setAttribute("orderItems",orderItems);}%><nav class="navbar-expand-lg navbar navbar-dark bg-primary"><div class="container-fluid "><a class="navbar-brand" href="#">订单详情页</a><button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNavDropdown"><ul class="navbar-nav"><li class="nav-item"><a class="nav-link active" aria-current="page" href="/MyProject/index.jsp">Home</a></li></ul></div></div></nav><c:if test="${!empty sessionScope.orderItems}"><div class="container"><div class="card"><table class="table table-hover text-center"><tr><td>订单号</td><td>商品名称</td><td>价格</td><td>数量</td><td>总价格</td></tr><c:forEach items="${sessionScope.orderItems}"var="orderItem"><tr style="vertical-align: middle !important;text-align: center;"><td>${orderItem.order_id}</td><td><img style="width: 100px;height: 100px" src="${orderItem.img}"/><span>${orderItem.name}</span></td><td>${orderItem.price}</td><td>${orderItem.count}</td><td>${orderItem.total_price}</td></tr></c:forEach></table></div></div></c:if></body></html>
订单详情的展示
在上边查看详情页按钮的代码中可以看到,跳转的不是
Controller
层,而是跳转到了
orderDetail.jsp
页面。在详情页面,通过请求携带的
订单Id
,来获取数据库的中的
订单项数据
。
不知道大家到这里会不会很奇怪?订单项是一个对象,订单也是一个对象。我们的订单和订单项的展示,都需要从数据库来获取,
那么这两个对象是什么时候存储到数据库中的呢?
别急。下边就是答案:
当我们在购物车中点击
结算
按钮的时候,他就会生成
订单对象
以及和它对应的
订单项
。
我们这里解释一下,它的前后端是如何处理的:
// 结算$("#settlement").click(function(){
$.post("/MyProject/orderProcessServlet",{method:""},function(data){if("success"== data){alert("订单生成成功!");
location.reload(true);}},"json")})
这段js代码在上一章节中,因为它属于购物车部分。是发送结算请求。请求地址是
/orderProcessServlet
,即我们的
订单对应的Controller层
。
OrderProcessServlet(订单处理层)
packagecom.controller;importcom.entity.*;importcom.google.gson.Gson;importcom.myUtil.JdbcUtil;importcom.myUtil.ProcessUtil;importcom.service.OrderService;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.servlet.http.HttpSession;importjava.io.IOException;publicclassOrderProcessServletextendsHttpServlet{privateOrderService orderService =newOrderService();@OverrideprotectedvoiddoPost(HttpServletRequest request,HttpServletResponse response)throwsIOException{HttpSession session = request.getSession();Cart cart =(Cart) session.getAttribute("cart");String userId =ProcessUtil.getUserIdBySessionId(session);if(cart==null|| cart.getItems().size()==0){
response.sendRedirect("/MyProject/index.jsp");return;}if(cart!=null){// 对生成订单进行事务控制String orderId =null;try{
orderId = orderService.saveOrder(cart,Integer.parseInt(userId));JdbcUtil.commit();
session.setAttribute("orderId",orderId);
response.getWriter().write(newGson().toJson("success"));}catch(Exception e){// 如果出错事务回滚JdbcUtil.rollback();
e.printStackTrace();}}}@OverrideprotectedvoiddoGet(HttpServletRequest request,HttpServletResponse response)throwsIOException{doPost(request, response);}}
orederService(订单处理的业务层)
packagecom.service;importcom.dao.GoodsDao;importcom.dao.OrderDao;importcom.dao.OrderItemDao;importcom.entity.*;importjava.time.LocalDateTime;importjava.util.HashMap;importjava.util.List;publicclassOrderService{privateOrderDao orderDao =newOrderDao();privateOrderItemDao orderItemDao =newOrderItemDao();privateGoodsDao goodsDao =newGoodsDao();// 生成订单publicStringsaveOrder(Cart cart,Integer userId){// 生成订单号String orderId =String.valueOf(System.currentTimeMillis());// 订单生成时间LocalDateTime createTime =LocalDateTime.now();Order order =newOrder(orderId,createTime,cart.getTotalPrice(),0,userId);// 保存order表到数据库
orderDao.addOrder(order);// 构建orderItem,并保存到数据库HashMap<Integer,ShopCarItem> items = cart.getItems();for(Integer goodId : items.keySet()){ShopCarItem item = items.get(goodId);OrderItem orderItem =newOrderItem(null, item.getImg(), item.getGoodsName(), item.getPrice(), item.getNumber(), item.getTotalPrice(), orderId);
orderItemDao.addOrderItem(orderItem);// 得到商品信息Goods goods = goodsDao.showDataById(String.valueOf(goodId));// 更新库存
goods.setInventory(goods.getInventory()- item.getNumber());// 更新到数据库
goodsDao.updateStock(goods);}// 清空购物车
cart.removeAll();return orderId;}// 显示所有订单publicList<Order>showAllOrder(String userId){return orderDao.showAllOrder(userId);}}
接着上边的逻辑,当
生成订单请求
发过来之后,在这
Controller
层调用
Service层
的
saveOrder()
进行了订单的生成,而且在
Service
层我们进行了
订单保存
,
订单项的保存
。而且我们注意到
saveOrder()
的参数是
Cart购物车对象
和
用户Id
。因为订单和订单项的所有信息都是从购物车来获取的,而且每个订单得有对应的用户(我们得保证自己的订单不能出现在别人的页面上,对吧^_^)。
当然生成订单之后还得清空购物车。
orderItemService
packagecom.service;importcom.dao.OrderItemDao;importcom.entity.OrderItem;importjava.util.List;publicclassOrderItemService{privateOrderItemDao orderItemDao =newOrderItemDao();// 显示所有订单项publicList<OrderItem>showAllOrderItem(String orderId){return orderItemDao.showAllOrderItem(orderId);}}
orderDao
packagecom.dao;importcom.entity.Order;importjava.util.List;publicclassOrderDaoextendsBasicDao<Order>{// 生成订单publicBooleanaddOrder(Order order){String sql ="INSERT INTO `order` VALUES('"+order.getId()+"','"+order.getCreate_time()+"',"+order.getPrice()+","+order.getStatus()+","+order.getMember_id()+")";returndmlData(sql);}// 显示所有订单publicList<Order>showAllOrder(String userId){String sql ="SELECT * FROM `order` WHERE `member_id`='"+ userId +"'";List<Order> orders =queryMulti(sql,Order.class);if(orders!=null){return orders;}returnnull;}}
orderItemDao
packagecom.dao;importcom.entity.OrderItem;importjava.util.List;publicclassOrderItemDaoextendsBasicDao<OrderItem>{// 添加订单项publicBooleanaddOrderItem(OrderItem orderItem){String sql ="INSERT INTO `order_item` VALUES(NULL,'"+ orderItem.getImg()+"','"+ orderItem.getName()+"',"+ orderItem.getPrice()+","+ orderItem.getCount()+","+ orderItem.getTotal_price()+",'"+ orderItem.getOrder_id()+"')";returndmlData(sql);}// 显示所有订单项publicList<OrderItem>showAllOrderItem(String orderId){String sql ="SELECT * FROM `order_item` WHERE `order_id`='"+ orderId +"'";List<OrderItem> orderItems =queryMulti(sql,OrderItem.class);if(orderItems !=null){return orderItems;}returnnull;}}
order(订单实体类)
订单实体类拥有属性:
- 订单号(订单结算的毫秒时间)
- 订单生成时间
- 订单金额
- 订单状态(这里我们没有太多的功能,所以默认是0)
- 订单所属者(每个订单属于哪个用户)
packagecom.entity;importjava.math.BigDecimal;importjava.time.LocalDateTime;publicclassOrder{// 订单号privateString id;// 订单生成时间privateLocalDateTime create_time;// 订单金额privateBigDecimal price;// 订单状态privateInteger status;// 该订单对应的用户idprivateInteger member_id;publicOrder(){}publicOrder(String id,LocalDateTime create_time,BigDecimal price,Integer status,Integer member_id){this.id = id;this.create_time = create_time;this.price = price;this.status = status;this.member_id = member_id;}publicStringgetId(){return id;}publicvoidsetId(String id){this.id = id;}publicLocalDateTimegetCreate_time(){return create_time;}publicvoidsetCreate_time(LocalDateTime create_time){this.create_time = create_time;}publicBigDecimalgetPrice(){return price;}publicvoidsetPrice(BigDecimal price){this.price = price;}publicIntegergetStatus(){return status;}publicvoidsetStatus(Integer status){this.status = status;}publicIntegergetMember_id(){return member_id;}publicvoidsetMember_id(Integer member_id){this.member_id = member_id;}@OverridepublicStringtoString(){return"Order{"+"id='"+ id +'\''+", create_time="+ create_time +", price="+ price +", status="+ status +", member_id="+ member_id +'}';}}
orderItem(订单项实体类)
订单项的实体类拥有的属性:
- 订单项唯一的标识Id
- 商品图片
- 商品的价格
- 商品数量
- 订单项的总价格
- 订单项的所属的订单(订单项都是从属于某一个订单)
packagecom.entity;importjava.math.BigDecimal;publicclassOrderItem{// 订单项的自增IDprivateInteger id;// 商品图片privateString img;// 商品名privateString name;// 商品价格privateBigDecimal price;// 商品数量privateInteger count;// 订单项的总价privateBigDecimal total_price;// 对应的订单号privateString order_id;publicOrderItem(){}@OverridepublicStringtoString(){return"OrderItem{"+"id="+ id +", img='"+ img +'\''+", name='"+ name +'\''+", price="+ price +", count="+ count +", total_price="+ total_price +", order_id='"+ order_id +'\''+'}';}publicStringgetImg(){return img;}publicvoidsetImg(String img){this.img = img;}publicOrderItem(Integer id,String img,String name,BigDecimal price,Integer count,BigDecimal total_price,String order_id){this.id = id;this.img = img;this.name = name;this.price = price;this.count = count;this.total_price = total_price;this.order_id = order_id;}publicIntegergetId(){return id;}publicvoidsetId(Integer id){this.id = id;}publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}publicBigDecimalgetPrice(){return price;}publicvoidsetPrice(BigDecimal price){this.price = price;}publicIntegergetCount(){return count;}publicvoidsetCount(Integer count){this.count = count;}publicBigDecimalgetTotal_price(){return total_price;}publicvoidsetTotal_price(BigDecimal total_price){this.total_price = total_price;}publicStringgetOrder_id(){return order_id;}publicvoidsetOrder_id(String order_id){this.order_id = order_id;}}
order表的设计
列名数据类型长度主键?非空?自增?idvarchar64√√create_timedatetime√pricedecimal11,2√statuetinyint32√memberint√
orderItem表的设计
列名数据类型长度主键?非空?自增?idint√√√imgvarchar500√namevarchar500√pricedecimal11,2√countint√total_pricedecimal11,2√order_idvarchar64√
这里我们得保证实体类的属性名要和对应表的字段名保持一致!!!
版权归原作者 艺术留白 所有, 如有侵权,请联系我们删除。