avatar

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

第五章 秒杀模块开发

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

1. 安装joda-time依赖

1
2
3
4
5
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.1</version>
</dependency>

可以创建DateTime类

2. 创建PromoModel秒杀模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

1
2
3
<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接口

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

PromoService实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@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中加入:

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

ItemServiceImpl加入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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中扩展秒杀活动的字段:

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

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

//秒杀活动ID
private Integer promoId;

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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中增加秒杀价格字段:

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

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

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

5.修改秒杀下单OrderService部分

在OrderService接口中:

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

在OrderServiceImpl中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//校验活动信息
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层增加参数:

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

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

5.3 项目总结

到这里我们全部完成了整个项目功能的开发,这个是入门课还存在很多问题比如:
5_01

文章作者: SkironYong
文章链接: https://skironyong.github.io/SkironYong.github.io/posts/297e61d6.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 SkironYong
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论