up:: SpringBoot电商项目订单模块前台创建订单接口

说明:

(1) 本篇博客的内容:开发【前台:订单详情】接口;

(2) 本篇博客的整体逻辑比较简单;需要注意的地方有两点:

● 要做好权限校验;

● 需要根据接口对返回数据的格式要求,去组织数据;


一:【前台:订单详情】接口介绍;

1.【前台:订单详情】接口,接口文档;


可以看到,接口要求的返回数据的格式,使用以前创建的Order和OrderItem去包装数据,都不能满足要求;

所以,为了能够更好的组织数据,以满足接口对返回数据格式的要求,我们创建了OrderVO实体类和OrderItemVO实体类:

OrderItemVO:

 
     package com.imooc.mall.model.vo;
 
     import java.util.Date;
 
     public class OrderItemVO {
 
         private String orderNo;
 
         private String productName;
 
         private String productImg;
 
         private Integer unitPrice;
 
         private Integer quantity;
 
         private Integer totalPrice;
 
         public String getOrderNo() {
             return orderNo;
         }
 
         public void setOrderNo(String orderNo) {
             this.orderNo = orderNo;
         }
 
         public String getProductName() {
             return productName;
         }
 
         public void setProductName(String productName) {
             this.productName = productName;
         }
 
         public String getProductImg() {
             return productImg;
         }
 
         public void setProductImg(String productImg) {
             this.productImg = productImg;
         }
 
         public Integer getUnitPrice() {
             return unitPrice;
         }
 
         public void setUnitPrice(Integer unitPrice) {
             this.unitPrice = unitPrice;
         }
 
         public Integer getQuantity() {
             return quantity;
         }
 
         public void setQuantity(Integer quantity) {
             this.quantity = quantity;
         }
 
         public Integer getTotalPrice() {
             return totalPrice;
         }
 
         public void setTotalPrice(Integer totalPrice) {
             this.totalPrice = totalPrice;
         }
     }
 

OrderVO:

 
     package com.imooc.mall.model.vo;
 
     import com.imooc.mall.model.pojo.OrderItem;
 
     import java.util.Date;
     import java.util.List;
 
     public class OrderVO {
         //很显然,我不能返回order表的id字段,否则会暴露我们商城的业务量这种秘密信息;
         //当然,接口中业没有要求返回order表的id信息;
         //    private Integer id;
         private String orderNo;
 
         private Integer userId;
 
         private Integer totalPrice;
 
         private String receiverName;
 
         private String receiverMobile;
 
         private String receiverAddress;
 
         private Integer orderStatus;
 
         private Integer postage;
 
         private Integer paymentType;
 
         private Date deliveryTime;
 
         private Date payTime;
 
         private Date endTime;
 
         private Date createTime;
 
         private Date updateTime;
 
         private String orderStatusName;
 
         private List<OrderItemVO> orderItemVOList;
 
         public String getOrderNo() {
             return orderNo;
         }
 
         public void setOrderNo(String orderNo) {
             this.orderNo = orderNo;
         }
 
         public Integer getUserId() {
             return userId;
         }
 
         public void setUserId(Integer userId) {
             this.userId = userId;
         }
 
         public Integer getTotalPrice() {
             return totalPrice;
         }
 
         public void setTotalPrice(Integer totalPrice) {
             this.totalPrice = totalPrice;
         }
 
         public String getReceiverName() {
             return receiverName;
         }
 
         public void setReceiverName(String receiverName) {
             this.receiverName = receiverName;
         }
 
         public String getReceiverMobile() {
             return receiverMobile;
         }
 
         public void setReceiverMobile(String receiverMobile) {
             this.receiverMobile = receiverMobile;
         }
 
         public String getReceiverAddress() {
             return receiverAddress;
         }
 
         public void setReceiverAddress(String receiverAddress) {
             this.receiverAddress = receiverAddress;
         }
 
         public Integer getOrderStatus() {
             return orderStatus;
         }
 
         public void setOrderStatus(Integer orderStatus) {
             this.orderStatus = orderStatus;
         }
 
         public Integer getPostage() {
             return postage;
         }
 
         public void setPostage(Integer postage) {
             this.postage = postage;
         }
 
         public Integer getPaymentType() {
             return paymentType;
         }
 
         public void setPaymentType(Integer paymentType) {
             this.paymentType = paymentType;
         }
 
         public Date getDeliveryTime() {
             return deliveryTime;
         }
 
         public void setDeliveryTime(Date deliveryTime) {
             this.deliveryTime = deliveryTime;
         }
 
         public Date getPayTime() {
             return payTime;
         }
 
         public void setPayTime(Date payTime) {
             this.payTime = payTime;
         }
 
         public Date getEndTime() {
             return endTime;
         }
 
         public void setEndTime(Date endTime) {
             this.endTime = endTime;
         }
 
         public Date getCreateTime() {
             return createTime;
         }
 
         public void setCreateTime(Date createTime) {
             this.createTime = createTime;
         }
 
         public Date getUpdateTime() {
             return updateTime;
         }
 
         public void setUpdateTime(Date updateTime) {
             this.updateTime = updateTime;
         }
 
         public String getOrderStatusName() {
             return orderStatusName;
         }
 
         public void setOrderStatusName(String orderStatusName) {
             this.orderStatusName = orderStatusName;
         }
 
         public List<OrderItemVO> getOrderItemVOList() {
             return orderItemVOList;
         }
 
         public void setOrderItemVOList(List<OrderItemVO> orderItemVOList) {
             this.orderItemVOList = orderItemVOList;
         }
     }
 
 

2.【前台:订单详情】接口,在界面上的表现;

我们可以点击某个订单,去查看订单详情;


二:正式开发;

1.在OrderController中,创建处理【前台:订单详情】接口请求的方法:detail()方法;

 
         /**
          * 【前台:订单详情】接口;
          * @param orderNo
          * @return
          */
         @ApiOperation("订单详情")
         @GetMapping("/order/detail")
         public ApiRestResponse detail(@RequestParam("orderNo") String orderNo) {
             OrderVO orderVO = orderService.detail(orderNo);
             return ApiRestResponse.success(orderVO);
         }

说明:

(1) 请求方式、url,参数,要符合接口要求;

(2) 我们在Service层,编写了一个获取订单详情的逻辑方法:detail()方法;这在下一部分介绍;

2.在OrderServiceImpl中,编写获取订单详情的逻辑方法:detail()方法;

 
      /**
          * 根据订单号,获取订单详情
          * @param orderNo
          * @return
          */
         @Override
         public OrderVO detail(String orderNo) {
             //首先,调用Dao层方法;根据订单号,去查询订单;
             Order order = orderMapper.selectByOrderNo(orderNo);
 
             //如果根据订单号,没有查到订单,就抛出“订单不存在”异常;
             if (order == null) {
                 throw new ImoocMallException(ImoocMallExceptionEnum.NO_ORDER);
             }
 
             //如果订单存在,还要看下,这个订单是不是属于当前登录用户的;(因为可能存在,A用户去查一个属于B用户的订单:产生横向越权)
             // 如果当前订单不属于当前登录用户,则抛出“订单不属于你”异常;
             Integer userId = UserFilter.currentUser.getId();
             if (!order.getUserId().equals(userId)) {
                 throw new ImoocMallException(ImoocMallExceptionEnum.NOT_YOUR_ORDER);
             }
 
             //调用工具方法:根据订单,按照接口对返回数据的要求,去组织订单详情数据
             OrderVO orderVO = getOrderVO(order);
 
             return orderVO;
         }
 
         /**
          * 根据order订单信息,拼装【接口要求的数据格式】:OrderVO
          * @param order
          */
         private OrderVO getOrderVO(Order order) {
             //(1),创建一个OrderVO,然后把【order中,与orderVO中重复的属性,,,复制到orderVO上去】
             OrderVO orderVO = new OrderVO();
             BeanUtils.copyProperties(order, orderVO);
 
             //(2),获取该订单的orderItemVOList(即,获取该订单中,每种商品的信息)
             //根据orderNo,获取对应的OrderItem信息;
             List<OrderItem> orderItemList = orderItemMapper.selectByOrderNo(order.getOrderNo());
             List<OrderItemVO> orderItemVOList = new ArrayList<>();
             //按照接口对返回数据的要求,把OrderItem转化为OrderItemVO;
             for (int i = 0; i < orderItemList.size(); i++) {
                 OrderItem orderItem = orderItemList.get(i);
                 OrderItemVO orderItemVO = new OrderItemVO();
                 BeanUtils.copyProperties(orderItem, orderItemVO);
                 orderItemVOList.add(orderItemVO);
             }
             //该订单的orderItemVOList,赋值给OrderVO;
             orderVO.setOrderItemVOList(orderItemVOList);
 
             //(3),获取待订单的订单状态码
             Integer orderStatus = order.getOrderStatus();
             //我们前面把订单状态定义在了枚举类中;借助我们定义的枚举,根据订单状态码获取订单状态的具体内容
             String orderStatusName = Constant.OrderStatusEnum.codeOf(orderStatus).getValue();
             //把订单状态的具体信息,赋值到OrderItem的属性上去
             orderVO.setOrderStatusName(orderStatusName);
 
             return orderVO;
         }

说明:

(1) 根据【接口要求的返回数据格式,我们创建了OrderVO这个实体类】;所以,我们detail()方法的返回值类型需要是OrderVO类型的;;也就是说,我们service层的方法,在获取到订单详情数据后,需要包装成OrderVO格式;

(2) 首先,我们要根据接口传过来的订单号,去order订单表中,去查;

● 这儿,我们在OrderMapper中,编写了一个根据订单号查询订单的方法:

(3) 如果,根据接口传的订单号,没有查到订单,我们就抛出“订单不存在”异常;

(4) 就算根据订单号查到了订单;但,发现查到的订单的所属用户和当前登录用户不一样;就抛出“这个订单不属于你”的异常;(否则就会产生横向越权)

(5) 然后,一切检查OK后,我们需要做的就是,组装符合接口要求格式的返回数据了;我们编写了getOrderVO()这个工具方法,用来拼装订单详情数据;

(6.1) 首先,我们需要把Order中,与OrderVO重复的属性,赋值给OrderVO对象;

(6.2) 然后,去查询该订单中的,每种商品的信息;也就是查询order_item表,得到OrderItem格式的数据;为此,我们在OrderItemMapper中,编写了一个根据订单号,查询该订单中是所有商品的方法;

(6.3) 然后,把查到的所有OrderItem格式的数据,转化为OrderItemVO格式的数据;

(6.4) 然后,把得到的List<OrderItemVO>赋值给OrderVO;

(6.5) 然后,就是根据订单状态码,获取订单状态信息,然后赋值给OrderVO了;

● 可以看到,这儿我们就用到了我们在【附加枚举类本篇博客没什么新的内容只是这儿用到了遍历枚举中枚举项的方法】中介绍的,使用到了遍历枚举的枚举项技术的codeOf()方法;

(7) 至此,OrderVO我们就组装好了;

(8) Service层,把这个组装好的OrderVO返回给Controller层;

3.在OrderService中,方向生成方法的定义;


三:测试;