架构师成长记_第三周_06_2020.11.08

订单功能实现

CTRL + ALT + O ( idea 快捷键删除多余的jar包依赖 )

枚举类 : 支付方式

package com.beyond.enums;


/**
 * @Description: 支付方式 枚举
 */
public enum  PayMethod {
    
    
    WEIXIN(1,"微信"),
    ALIPAY(2,"支付宝");
    public final Integer type;
    public final String value;

    PayMethod(Integer type, String value){
    
    
        this.type = type;
        this.value = value;
    }

}

BO : SubmitOrderBO

package com.beyond.pojo.bo;


/**
 * 用于创建订单的BO对象
 */
public class SubmitOrderBO {
    
    

    private String userId;
    private String itemSpecIds;
    private String addressId;
    private Integer payMethod;
    private String leftMsg;


    public String getUserId() {
    
    
        return userId;
    }

    public void setUserId(String userId) {
    
    
        this.userId = userId;
    }

    public String getItemSpecIds() {
    
    
        return itemSpecIds;
    }

    public void setItemSpecIds(String itemSpecIds) {
    
    
        this.itemSpecIds = itemSpecIds;
    }

    public String getAddressId() {
    
    
        return addressId;
    }

    public void setAddressId(String addressId) {
    
    
        this.addressId = addressId;
    }

    public Integer getPayMethod() {
    
    
        return payMethod;
    }

    public void setPayMethod(Integer payMethod) {
    
    
        this.payMethod = payMethod;
    }

    public String getLeftMsg() {
    
    
        return leftMsg;
    }

    public void setLeftMsg(String leftMsg) {
    
    
        this.leftMsg = leftMsg;
    }

	   @Override
    public String toString() {
    
    
        return "SubmitOrderBO{" +
                "userId='" + userId + '\'' +
                ", itemSpecIds='" + itemSpecIds + '\'' +
                ", addressId='" + addressId + '\'' +
                ", payMethod=" + payMethod +
                ", leftMsg='" + leftMsg + '\'' +
                '}';
    }
}

Controller : OrdersController

package com.beyond.controller;

import com.beyond.enums.PayMethod;
import com.beyond.pojo.bo.SubmitOrderBO;
import com.beyond.service.OrderService;
import com.beyond.utils.BEYONDJSONResult;
import com.beyond.utils.CookieUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Api(value = "与订单相关",tags = {
    
    "订单相关的接口"})
@RestController
@RequestMapping("orders")
public class OrdersController extends BaseController {
    
    

    @Autowired
    private OrderService orderService;

    @ApiOperation(value = "用户订单功能",notes = "用户订单功能 ",httpMethod = "POST")
    @PostMapping("/create")
    public BEYONDJSONResult create(
            @RequestBody SubmitOrderBO submitOrderBO,   // 该注解表示接收一个json对象
            HttpServletRequest request,
            HttpServletResponse response
    ){
    
    

        if (submitOrderBO.getPayMethod() != PayMethod.WEIXIN.type
                && submitOrderBO.getPayMethod() != PayMethod.ALIPAY.type
        ){
    
    
            return BEYONDJSONResult.errorMsg("支付方式不支持");
        }

        System.out.println(submitOrderBO.toString());

        // 1. 创建订单
        String orderId = orderService.createOrder(submitOrderBO);

        // 2. 创建订单后移除中已结算(已提交)的商品

         // TODO 整合redis之后, 完善购物车中已结算商品清除, 并且同步到前端的cookie
        CookieUtils.setCookie(request, response,  COOKIE_SHOPCART, "",true);

        // 3. 向支付中心发送当前订单, 用于保存支付中心的订单







        return BEYONDJSONResult.ok(orderId);
    }


}

完善 AddressService

 /**
     * 根据传人的用户id 和地址id 查找用户的地址信息
     * @param userId
     * @param addressId
     */
    public UserAddress queryUserAddress(String userId,String addressId);

完善 AddressServiceImpl

 @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public UserAddress queryUserAddress(String userId, String addressId) {
    
    
        UserAddress userAddress = new UserAddress();
        userAddress.setUserId(userId);
        userAddress.setId(addressId);

        return userAddressMapper.selectOne(userAddress);
    }

Service : 完善 ItemService

    /**
     * 根据商品Id 获取商品的规格信息
     * @param specId
     * @return
     */
    public ItemsSpec queryItemSpecById(String specId);


    /**
     * 根据商品id 获得商品主图
     * @param itemId
     * @return
     */
    public String queryItemMainImgById(String itemId);


	/**
     * 更新库存
     * @param specId
     * @param buyCounts
     */
    public void decreaseItemSpecStock(String specId, Integer buyCounts);

ServiceImpl : 完善 ItemServiceImpl

 @Override
    public ItemsSpec queryItemSpecById(String specId) {
    
    
        return itemsSpecMapper.selectByPrimaryKey(specId);
    }


 @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public String queryItemMainImgById(String itemId) {
    
    
        ItemsImg itemsImg = new ItemsImg();
        itemsImg.setItemId(itemId);
        itemsImg.setIsMain(YesOrNo.YES.type);
        ItemsImg result = itemsImgMapper.selectOne(itemsImg);
        return result != null ? result.getUrl() : "";
    }

@Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void decreaseItemSpecStock(String specId, Integer buyCounts) {
    
    

            // synchronized 不推荐使用, 在集群环境下无效, 性能低下
            // 不能锁数据库, 也导致数据库性能低下, 且一旦发生故障则无法承担后果
            // 可以使用分布式锁 zookeeper redis
        // 这里使用对 mapper 的乐观锁实现 避免超卖处理

        int result = itemsMapperCustom.decreaseItemSpecStock(specId, buyCounts);
        if (result != 1){
    
    
            throw new RuntimeException("订单创建失败, 库存不足!");
        }


Enum : OrderStatusEnum

package com.beyond.enums;

/**
 * @Description : 订单状态 枚举
 */
public enum OrderStatusEnum {
    
    
    WAIT_PAY(10,"待付款"),
    WAIT_DELIVER(20,"已付款, 待发货"),
    WAIT_RECEIVE(30,"已发货, 待收货"),
    SUCCESS(40,"交易成功"),
    CLOSE(50,"交易关闭");

    public final Integer type;
    public final String value;

    OrderStatusEnum(Integer type, String value){
    
    
        this.type = type;
        this.value = value;
    }
}

完善Mapper : ItemsMapperCustom

ItemsMapperCustom.xml


<!--    使用 乐观锁机制实现并发超卖处理-->
    <update id="decreaseItemSpecStock" >
        update
            items_spec
        set stock = stock - #{
    
    pendingCounts}
        where
        id = #{
    
    specId} and stock >= #{
    
    pendingCounts}
    </update>

ItemsMapperCustom.java

    public int decreaseItemSpecStock(@Param("specId") String specId,
                                     @Param("pendingCounts") int pendingCounts);

Service : OrderService

package com.beyond.service;

import com.beyond.pojo.bo.SubmitOrderBO;


public interface OrderService {
    
    

    public String createOrder(SubmitOrderBO submitOrderBO);


}

ServiceImpl : OrderServiceImpl

package com.beyond.service.impl;

import com.beyond.enums.OrderStatusEnum;
import com.beyond.enums.YesOrNo;
import com.beyond.mapper.OrderItemsMapper;
import com.beyond.mapper.OrderStatusMapper;
import com.beyond.mapper.OrdersMapper;
import com.beyond.pojo.*;
import com.beyond.pojo.bo.SubmitOrderBO;
import com.beyond.service.AddressService;
import com.beyond.service.ItemService;
import com.beyond.service.OrderService;
import org.n3r.idworker.Sid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;


@SuppressWarnings("ALL")
@Service
public class OrderServiceImpl implements OrderService {
    
    

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private AddressService addressService;

    @Autowired
    private Sid sid;

    @Autowired
    private ItemService itemService;

    @Autowired
    private OrderItemsMapper orderItemsMapper;

    @Autowired
    private OrderStatusMapper orderStatusMapper;



    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public String createOrder(SubmitOrderBO submitOrderBO) {
    
    
        String userId = submitOrderBO.getUserId();
        String addressId = submitOrderBO.getAddressId();
        String itemSpecIds = submitOrderBO.getItemSpecIds();
        Integer payMethod = submitOrderBO.getPayMethod();
        String leftMsg = submitOrderBO.getLeftMsg();
        // 包邮费用设置为0
        Integer postAmount = 0;

        String orderId = sid.nextShort();

        // 1. 新订单数据保存
        Orders newOrder = new Orders();
        newOrder.setId(orderId);
        newOrder.setUserId(userId);
        UserAddress userAddress = addressService.queryUserAddress(userId, addressId);

        newOrder.setReceiverName(userAddress.getReceiver());
        newOrder.setReceiverMobile(userAddress.getMobile());
        newOrder.setReceiverAddress(userAddress.getProvince()+" "
                +userAddress.getCity()+" "
                +userAddress.getDistrict()+" "
                +userAddress.getDetail()  );


        newOrder.setPostAmount(postAmount);
        newOrder.setLeftMsg(leftMsg);
        newOrder.setPayMethod(payMethod);
        newOrder.setIsComment(YesOrNo.NO.type);
        newOrder.setIsDelete(YesOrNo.NO.type);
        newOrder.setCreatedTime(new Date());
        newOrder.setUpdatedTime(new Date());


        // 2. 循环根据itemSpecIds保存订单商品信息表
        String[] itemSpecIdArr = itemSpecIds.split(",");
        Integer totalAmount = 0; // 商品的原价累计
        Integer realPayAmount = 0; // 商品优惠后的价格统计
        for (String itemSpecId :   itemSpecIdArr){
    
    

            // TODO 整合 redis后, 商品购买的数量重新从redis的购物车中获取
            int buyCounts = 1;

            // 2.1 根据规格id, 查询规格的具体信息, 主要获取价格
            ItemsSpec itemsSpec = itemService.queryItemSpecById(itemSpecId);
            totalAmount += itemsSpec.getPriceNormal() * buyCounts;
            realPayAmount += itemsSpec.getPriceDiscount() * buyCounts;

            // 2.2 根据商品id 获得商品信息和商品图片
            String itemId = itemsSpec.getItemId();
            Items items = itemService.queryItemById(itemId);
            String imgUrl = itemService.queryItemMainImgById(itemId);

            // 2.3 循环保存子订单数据到数据库
            OrderItems subOrderItem = new OrderItems();
            String subOrderId = sid.nextShort();
            subOrderItem.setId(subOrderId);
            subOrderItem.setOrderId(orderId);
            subOrderItem.setItemId(itemId);
            subOrderItem.setItemName(items.getItemName());
            subOrderItem.setItemImg(imgUrl);
            subOrderItem.setBuyCounts(buyCounts);
            subOrderItem.setItemSpecId(itemSpecId);
            subOrderItem.setItemSpecName(itemsSpec.getName());
            subOrderItem.setPrice(itemsSpec.getPriceDiscount());

            orderItemsMapper.insert(subOrderItem);


            // 2.4 在用户购买后应该匹配好库存, 扣除库存
            itemService.decreaseItemSpecStock(itemSpecId,buyCounts);
        }

        newOrder.setTotalAmount(totalAmount);
        newOrder.setRealPayAmount(realPayAmount);
        ordersMapper.insert(newOrder);



        // 3. 保存订单状态表
        OrderStatus waitPayOrderStatus = new OrderStatus();
        waitPayOrderStatus.setOrderId(orderId);
        waitPayOrderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.type);
        waitPayOrderStatus.setCreatedTime(new Date());
        orderStatusMapper.insert(waitPayOrderStatus);

        return orderId;

    }



}

猜你喜欢

转载自blog.csdn.net/Beyond_Nothing/article/details/111772386