SpringBoot构建电商秒杀项目(五)秒杀模块开发

第五章 秒杀模块开发

5.1 秒杀模型管理——活动模型创建

1. 安装joda-time依赖

<dependency>
  <groupId>joda-time</groupId>
  <artifactId>joda-time</artifactId>
  <version>2.9.1</version>
</dependency>

可以创建DateTime类

2. 创建PromoModel秒杀模型

public class PromoModel {
     
    private Integer id;

    //秒杀活动状态:1表示还未开始,2表示正在进行,3表示已结束
    private Integer status;

    
    //秒杀活动名称
    private String promoName;

    //秒杀活动的开始时间
    private DateTime startDate;

    //秒杀活动的结束时间
    private DateTime endDate;

    //秒杀活动的适用商品
    private Integer itemId;

    //秒杀活动的商品价格
    private BigDecimal promoItemPrice;

3. 数据库创建promo表

类型 说明
id int 秒杀活动id
promo_name varchar 秒杀活动名称
start_date datetime 秒杀活动开始时间
end_date datetime 秒杀活动结束时间
item_id int 秒杀活动适用商品
promo_item_price double 秒杀活动商品价格

注意:数据库datetime默认值要设置为’0000-00-00 00:00:00’格式

4. mybatis-generator工具生成PromoDO类和PromoDOMapper

运行 mvn mybatis-generator:generate

<table  tableName="promo" domainObjectName="PromoDO" enableCountByExample="false"
                enableUpdateByExample="false" enableDeleteByExample="false"
                enableSelectByExample="false" selectByExampleQueryId="false">table>

5.2 秒杀模型管理——活动模型与商品模型结合

1. Service层创建PromoSerice接口与实现类

秒杀活动service层主要的操作是:

  • 根据itemId来获取即将进行的或正在进行的秒杀活动信息(返回PromoDO的dataObject)
  • 将PromoDO转化为PromoModel
  • 根据status来判断当前时间是否即将开始或正在进行秒杀活动
  • 返回promoModel对象

PromoService接口

//根据itemId获取即将进行的或者正在进行的秒杀活动
    PromoModel getPromoByItemId(Integer itemId);

PromoService实现类

@Service
public class PromoServiceImpl implements PromoService {
     

    @Resource
    private PromoDOMapper promoDOMapper;

    @Override
    public PromoModel getPromoByItemId(Integer itemId) {
     
        //获取对应商品的秒杀活动信息
        PromoDO promoDO = promoDOMapper.selectByItemId(itemId);

        //promoDo(dataObject) -> PromoModel
        PromoModel promoModel = convertFromDataObject(promoDO);
        if(promoModel == null) {
     
            return null;
        }
        //判断当前时间是否秒杀活动即将开始或正在进行
        DateTime now = new DateTime();
        if(promoModel.getStartDate().isAfterNow()) {
     
            promoModel.setStatus(1);
        }else if(promoModel.getEndDate().isBeforeNow()) {
     
            promoModel.setStatus(3);
        }else {
     
            promoModel.setStatus(2);
        }
        return promoModel ;
    }
    private PromoModel convertFromDataObject(PromoDO promoDO) {
     
        if(promoDO == null) {
     
            return null;
        }
        PromoModel promoModel = new PromoModel();
        BeanUtils.copyProperties(promoDO,promoModel);
        //copyProperties后漏掉的属性
        promoModel.setPromoItemPrice(new BigDecimal(promoDO.getPromoItemPrice()));//数据库存的是double类型
        promoModel.setStartDate(new DateTime(promoDO.getStartDate()));
        promoModel.setEndDate(new DateTime(promoDO.getEndDate()));
        return promoModel;
    }
}

2. 使用聚合模型,在ItemModel嵌套秒杀活动属性

ItemModel中加入:

//使用聚合模型(Java类嵌套),如果promoModel不为空,则表示其拥有还未结束的秒杀活动
private PromoModel promoModel;

ItemServiceImpl加入:

@Override
public ItemModel getItemById(Integer id) {
     
    ItemDO itemDO = itemDOMapper.selectByPrimaryKey(id);
    if (itemDO == null) {
     
        return null;
    }
    //操作获得库存数量
    ItemStockDO itemStockDO = itemStockDOMapper.selectByItemId(itemDO.getId());

    //将dataobject-> Model
    ItemModel itemModel = convertModelFromDataObject(itemDO, itemStockDO);

    //获取活动商品信息
    PromoModel promoModel = promoService.getPromoByItemId(itemModel.getId());
    if (promoModel != null && promoModel.getStatus().intValue() != 3) {
     
        itemModel.setPromoModel(promoModel);
    }
    return itemModel;
}

在ItemVO中扩展秒杀活动的字段:

//记录商品是否在秒杀活动中,以及对应的状态 0表示没有秒杀活动,1表示秒杀活动待开始,2表示秒杀活动进行中
    private Integer promoStatus;

    //秒杀活动价格
    private BigDecimal promoPrice;

    //秒杀活动ID
    private Integer promoId;

    //秒杀活动开始时间
    private String startDate;

在ItemController中向itemVO增加秒杀活动信息:

    private ItemVO convertVOFromModel(ItemModel itemModel) {
     
          if(itemModel == null) {
     
                return null;
          }
         ItemVO itemVO = new ItemVO();
         BeanUtils.copyProperties(itemModel,itemVO);

         if(itemModel.getPromoModel()!=null) {
     
             //有正在进行或即将进行的秒杀活动
             itemVO.setPromoStatus(itemModel.getPromoModel().getStatus());
             itemVO.setPromoId(itemModel.getPromoModel().getId());
             itemVO.setStartDate(itemModel.getPromoModel().getStartDate().toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")));
             itemVO.setPromoPrice(itemModel.getPromoModel().getPromoItemPrice());
         }else {
     
             itemVO.setPromoStatus(3);
         }
         return itemVO;
        }

3.修改商品详情getItem前端页面

增加秒杀活动状态、时间、秒杀价格以及倒计时的显示

4.修改秒杀下单OrderModel部分

在OrderModel中增加秒杀价格字段:

//若非空,则表示是以秒杀商品方式下单
private Integer promoId;

//购买时商品的单价,若promoId非空,则表示是以秒杀商品方式下单
private BigDecimal itemPrice;

同步的在数据库order_info表加入promo_id字段,OrderDO与OrderDOMapper中加入PromoId字段

5.修改秒杀下单OrderService部分

在OrderService接口中:

//1.通过url上传过来秒杀活动id,然后下单接口内校验对应id是否属于对应商品且活动已开始
//2.直接在下单接口内判断对应的商品是否存在秒杀活动,若存在进行中的则以秒杀价格下单
//倾向于使用第一种形式,因为对同一个商品可能存在不同的秒杀活动,而且第二种方案普通销售的商品也需要校验秒杀
OrderModel createOrder(Integer userId, Integer itemId, Integer promoId, Integer amount) throws BusinessException;

在OrderServiceImpl中:

//校验活动信息
        if(promoId!=null) {
     
            //(1)校验对应活动是否存在在这个适用商品
            if(promoId.intValue()!=itemModel.getPromoModel().getId()) {
     
                throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"活动信息不正常");
            //(2)校验活动是否正在进行中
            }else if(itemModel.getPromoModel().getStatus().intValue()!=2) {
     
                throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"活动信息还未开始");
            }
        }

        //2.落单减库存(还有一种:支付减库存(先支付成功,再看库存量)
        boolean result = itemService.decreaseStock(itemId,amount);
        if(!result) {
     
            throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH);
        }
        //3.订单入库
        OrderModel orderModel = new OrderModel();
        orderModel.setUserId(userId);
        orderModel.setItemId(itemId);
        orderModel.setAmount(amount);
        orderModel.setPromoId(promoId);
        //是秒杀活动,价格为秒杀价格,否则为平销价格
        if(promoId != null) {
     
            orderModel.setItemPrice(itemModel.getPromoModel().getPromoItemPrice());
        }else {
     
            orderModel.setItemPrice(itemModel.getPrice());
        }
        orderModel.setOrderPrice(orderModel.getItemPrice().multiply(new BigDecimal(amount)));

6.修改秒杀下单OrderController部分

在controller层增加参数:

@RequestParam(name = "promoId",required = false) Integer promoId,

修改前端页面:
测试-------》成功

5.3 项目总结

到这里我们全部完成了整个项目功能的开发,这个是入门课还存在很多问题比如: SpringBoot构建电商秒杀项目(五)秒杀模块开发_第1张图片


【系列笔记已经更新完毕】

  • SpringBoot构建电商秒杀项目(一) 基础项目的搭建
  • SpringBoot构建电商秒杀项目(二) 用户模块开发
  • SpringBoot构建电商秒杀项目(三) 商品模块开发
  • SpringBoot构建电商秒杀项目(四)交易模块开发
  • SpringBoot构建电商秒杀项目(五)秒杀模块开发
    后续还有进阶课程 聚焦Java性能优化 打造亿级流量秒杀系统
    欢迎来我的博客skiron.xyz来玩啊

你可能感兴趣的:(java,spring,boot)