请求入队,客户端轮询

一、客户端轮询

<script>

function getMiaoshaResult(goodsId){//做一个查询
g_showLoading();//加载中
$.ajax({
url: '/miaosha/result',  // 调用后台轮询功能的接口
type: "GET",
data: {//post提交表单的时候,url参数可以放在data中
goodsId: goodsId
//goodsId: $("#goodsId").val()
},
success:function(data){//成功的时候会有一个回调,data是返回的数据,该数据应该是一个对象类型,或字典类型
var result = data.data;
if(data.code == 0){
if(result > 0){//秒杀成功
layer.confirm("秒杀成功,查看订单?",{btn: ["确定","取消"]},
function(){
window.location.href="/order_detail.htm?orderId=" + result;
},function(){
layer.closeAll();
}
);
}else if(result == 0){//排队中
//继续轮询
setTimeout(getMiaoshaResult(goodsId),50);//50毫秒
}else{//秒杀失败
layer.msg("秒杀失败");
}
}else{
layer.msg(data.msg);
}
},
error:function(){
layer.msg("客户端请求有误");
}
});
}


function doMiaosha(){//秒杀的时候,需要向服务端传递参数

$.ajax({
url: '/miaosha/do_miaosha',  // 调用后台的实现秒杀功能的接口
type: "POST",
data: {
goodsId: $("#goodsId").val()
},
success:function(data){//成功的时候会有一个回调,data是返回的数据,该数据应该是一个对象类型,或字典类型
if(data.code == 0){
/* render(data.data);//这里需要一个渲染页面的函数 render */
//window.location.href="/order_detail.htm?orderId=" + data.data.id;
getMiaoshaResult($("#goodsId").val());
}else{
layer.msg(data.msg);
}
},
error:function(){
layer.msg("客户端请求有误");
}
});

}

二、后台接口

后台的实现秒杀功能的接口:

@RequestMapping(value="/do_miaosha", method=RequestMethod.POST)
@ResponseBody
    public Result<Integer> miaosha(MiaoshaUser user, @RequestParam("goodsId")long goodsId) {
//RequestParam可以把保单隐含提交的input标签对应name属性的元素取出
if(user == null){
return Result.error(CodeMsg.SESSION_ERROR);
}
//判断内存标记
boolean over = isOverMap.get(goodsId);
if(over){
return Result.error(CodeMsg.MIAO_SHA_OVER);
}

//预减库存
long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, "" + goodsId);
if(stock < 0){
isOverMap.put(goodsId, true);
return Result.error(CodeMsg.MIAO_SHA_OVER);
}
//判断是否已经进行了秒杀
MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
if(miaoshaOrder != null){
return Result.error(CodeMsg.REPEAT_MIAOSHA);
}
//入队
MiaoshaMessage mm = new MiaoshaMessage();
mm.setMiaoshaUser(user);
mm.setGoodsId(goodsId);
sender.sendMiaoshsaMessage(mm);
return Result.success(0);

}

后台轮询功能的接口:

/*

* orderId: 成功
* -1   : 秒杀失败
* 0 : 还在排队

* */
@RequestMapping(value="/result", method=RequestMethod.GET)
@ResponseBody
    public Result<Long> result(MiaoshaUser user, @RequestParam("goodsId")long goodsId) {
//RequestParam可以把保单隐含提交的input标签对应name属性的元素取出
if(user == null){
return Result.error(CodeMsg.SESSION_ERROR);
}
//根据result的三种数值范围,来判断下一步的操作
long result = miaoshaService.getMiaoshaResult(user.getId(), goodsId);
return Result.success(result);

}

MiaoshaService:

@Transactional
public OrderInfo miaosha(MiaoshaUser user, GoodsVo goodsVo) {
//减库存(减miaosha_goods的库存), 写入秒杀订单
boolean success = goodsService.reduceStock(goodsVo);
if(success){
//下订单, 包含两步:一、order_info  二、miaosha_order  实际上是两步操作
return orderService.createOrder(user, goodsVo);
}else{//商品已经被秒杀完了
setGoodsOver(goodsVo.getId());
return null;
}
}
public long getMiaoshaResult(Long userId, long goodsId) {
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(userId, goodsId);
if(order != null){//说明本次查询的时候,已经秒杀成功了
return order.getOrderId();
}else{
boolean isOver = getGoodsOver(goodsId);
if(isOver){
return -1; //代表卖完了
}else{
return 0; //继续轮询
}
}

}

private void setGoodsOver(Long id) {
redisService.set(MiaoshaKey.isGoodsOver, "" + id, true);
}
private boolean getGoodsOver(long goodsId) {
return redisService.exists(MiaoshaKey.isGoodsOver, "" + goodsId);
}

三、出队

@RabbitListener(queues=MQConfig.MIAOSHA_QUEUE)
public void receiverMiaosha(String message){
logger.info("receiver message: " + message);在接收消息的时候,就可以将字符串转换为对象了,然后对对象进行处理
MiaoshaMessage miaoshaMessage = RedisService.stringToBean(message, MiaoshaMessage.class);
MiaoshaUser user = miaoshaMessage.getMiaoshaUser();
long goodsId = miaoshaMessage.getGoodsId();
//收到消息之后做的事情和controller做的事情是一样的
GoodsVo goodsVo = goodsService.getOneGoodsVoById(goodsId);
int stockCount = goodsVo.getStockCount();
if(stockCount <= 0){
return;
}
//防止一个人秒杀多个商品,判断是否已经秒杀到了  ==> 到OrderService中去查找(查找生成的秒杀类型的订单,这种订单必须是一个用户和一个特价商品关联产生的,且每个用户只能产生一个)
MiaoshaOrder miaoshaOrder = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
if(miaoshaOrder != null){
return;
}
//减库存,下(写)订单,写入秒杀订单(需要在一个事物当中去做,搞一个service,做一个MiaoshaService,然后进行一个Transaction操作)
OrderInfo orderInfo = miaoshaService.miaosha(user, goodsVo);//为什么成功了以后要返回订单呢?因为我们想秒杀成功之后直接进入到订单详情页
//把订单的详细信息写入到我们的页面上
//return Result.success(orderInfo);
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值