当前位置: 首页 > news >正文

网站做seo第一步百度seo有用吗

网站做seo第一步,百度seo有用吗,网站空间到期时间查询,盐城手机网站制作目录: (1)整合秒杀业务 (2)秒杀下单 (3)秒杀下单监听 (4)页面轮询接口 (1)整合秒杀业务 秒杀的主要目的就是获取一个下单资格,拥…

目录:

(1)整合秒杀业务

(2)秒杀下单

(3)秒杀下单监听

(4)页面轮询接口

(1)整合秒杀业务

秒杀的主要目的就是获取一个下单资格,拥有下单资格就可以去下单支付,获取下单资格后的流程就与正常下单流程一样,只是没有购物车这一 步,总结起来就是,秒杀根据库存获取下单资格,拥有下单资格进入下单页面(选择地址,支付方式,提交订单,然后支付订单)

步骤:

  1. 校验下单码,只有正确获得下单码的请求才是合法请求
  2. 校验状态位state

State为null,说明非法请求;

State0说明已经售罄;

State为1,说明可以抢购

状态位是在内存中判断,效率极高,如果售罄,直接就返回了,不会给服务器造成太大压力

  1. 前面条件都成立,将秒杀用户加入队列,然后直接返回
  2. 前端轮询秒杀状态,查询秒杀结果

(2)秒杀下单

添加mq常量MqConst

/*** 秒杀*/
public static final String EXCHANGE_DIRECT_SECKILL_USER = "exchange.direct.seckill.user";
public static final String ROUTING_SECKILL_USER = "seckill.user";
//队列
public static final String QUEUE_SECKILL_USER  = "queue.seckill.user";

定义实体UserRecode

记录哪个用户要购买哪个商品!

@Data
public class UserRecode implements Serializable {private static final long serialVersionUID = 1L;private Long skuId;private String userId;
}

编写控制器SeckillGoodsApiController

@Autowired
private RabbitService rabbitService;
/*** 根据用户和商品ID实现秒杀下单* @param skuId* @return*/
@PostMapping("auth/seckillOrder/{skuId}")
public Result seckillOrder(@PathVariable("skuId") Long skuId, HttpServletRequest request) throws Exception {//校验下单码(抢购码规则可以自定义)String userId = AuthContextHolder.getUserId(request);String skuIdStr = request.getParameter("skuIdStr");if (!skuIdStr.equals(MD5.encrypt(userId))) {//请求不合法return Result.build(null, ResultCodeEnum.SECKILL_ILLEGAL);}//校验状态位//产品标识, 1:可以秒杀 0:秒杀结束String state = (String) CacheHelper.get(skuId.toString());if (StringUtils.isEmpty(state)) {//请求不合法return Result.build(null, ResultCodeEnum.SECKILL_ILLEGAL);}if ("1".equals(state)) {//用户记录UserRecode userRecode = new UserRecode();userRecode.setUserId(userId);userRecode.setSkuId(skuId);//发送消息rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_SECKILL_USER, MqConst.ROUTING_SECKILL_USER, userRecode);} else {//已售罄return Result.build(null, ResultCodeEnum.SECKILL_FINISH);}return Result.ok();
}

全局统一返回结果类: 

package com.atguigu.gmall.common.result;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** 全局统一返回结果类**/
@Data
@ApiModel(value = "全局统一返回结果")
public class Result<T> {@ApiModelProperty(value = "返回码")private Integer code;@ApiModelProperty(value = "返回消息")private String message;@ApiModelProperty(value = "返回数据")private T data;public Result(){}// 返回数据protected static <T> Result<T> build(T data) {Result<T> result = new Result<T>();if (data != null)result.setData(data);return result;}public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {Result<T> result = build(body);result.setCode(resultCodeEnum.getCode());result.setMessage(resultCodeEnum.getMessage());return result;}public static<T> Result<T> ok(){return Result.ok(null);}/*** 操作成功* @param data* @param <T>* @return*/public static<T> Result<T> ok(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.SUCCESS);}public static<T> Result<T> fail(){return Result.fail(null);}/*** 操作失败* @param data* @param <T>* @return*/public static<T> Result<T> fail(T data){Result<T> result = build(data);return build(data, ResultCodeEnum.FAIL);}public Result<T> message(String msg){this.setMessage(msg);return this;}public Result<T> code(Integer code){this.setCode(code);return this;}public boolean isOk() {if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {return true;}return false;}
}

统一返回结果状态信息类:

package com.atguigu.gmall.common.result;import lombok.Getter;/*** 统一返回结果状态信息类**/
@Getter
public enum ResultCodeEnum {SUCCESS(200,"成功"),FAIL(201, "失败"),SERVICE_ERROR(2012, "服务异常"),ILLEGAL_REQUEST( 204, "非法请求"),PAY_RUN(205, "支付中"),LOGIN_AUTH(208, "未登陆"),PERMISSION(209, "没有权限"),SECKILL_NO_START(210, "秒杀还没开始"),SECKILL_RUN(211, "正在排队中"),SECKILL_NO_PAY_ORDER(212, "您有未支付的订单"),SECKILL_FINISH(213, "已售罄"),SECKILL_END(214, "秒杀已结束"),SECKILL_SUCCESS(215, "抢单成功"),SECKILL_FAIL(216, "抢单失败"),SECKILL_ILLEGAL(217, "请求不合法"),SECKILL_ORDER_SUCCESS(218, "下单成功"),COUPON_GET(220, "优惠券已经领取"),COUPON_LIMIT_GET(221, "优惠券已发放完毕"),;private Integer code;private String message;private ResultCodeEnum(Integer code, String message) {this.code = code;this.message = message;}
}

(3)秒杀下单监听

思路:

  1. 首先判断产品状态位,我们前面不是已经判断过了吗?因为产品可能随时售罄,mq队列里面可能堆积了十万数据,但是已经售罄了,那么后续流程就没有必要再走了;
  2. 判断用户是否已经下过订单,这个地方就是控制用户重复下单,同一个用户只能抢购一个下单资格,怎么控制呢?很简单,我们可以利用setnx控制用户,当用户第一次进来时,返回true,可以抢购,以后进入返回false,直接返回,过期时间可以根据业务自定义,这样用户这一段咋们就控制注了
  3. 获取队列中的商品,如果能够获取,则商品有库存,可以下单。如果获取的商品id为空,则商品售罄,商品售罄我们要第一时间通知兄弟节点,更新状态位,所以在这里发送redis广播
  4. 将订单记录放入redis缓存,说明用户已经获得下单资格,秒杀成功
  5. 秒杀成功要更新库存

SeckillReceiver添加监听方法

@Autowired
private SeckillGoodsService seckillGoodsService;//  监听用户与商品的消息!
@SneakyThrows
@RabbitListener(bindings = @QueueBinding(value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),key = {MqConst.ROUTING_SECKILL_USER}
))
public void seckillUser(UserRecode userRecode,Message message,Channel channel){try {//  判断接收过来的数据if (userRecode!=null){//  预下单处理!seckillGoodsService.seckillOrder(userRecode.getSkuId(),userRecode.getUserId());}} catch (Exception e) {e.printStackTrace();}//  手动确认channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
}

预下单接口SeckillGoodsService接口


/*** 根据用户和商品ID实现秒杀下单* @param skuId* @param userId*/
void seckillOrder(Long skuId, String userId);

秒杀订单实体类

package com.atguigu.gmall.model.activity;@Data
public class OrderRecode implements Serializable {private static final long serialVersionUID = 1L;private String userId;private SeckillGoods seckillGoods;private Integer num;private String orderStr;
}

 实现类

/**** 创建订单* @param skuId* @param userId*/
@Override
public void seckillOrder(Long skuId, String userId) {//产品状态位, 1:可以秒杀 0:秒杀结束String state = (String) CacheHelper.get(skuId.toString());if("0".equals(state)) {//已售罄return;}//判断用户是否下单boolean isExist = redisTemplate.opsForValue().setIfAbsent(RedisConst.SECKILL_USER + userId, skuId.toString(), RedisConst.SECKILL__TIMEOUT, TimeUnit.SECONDS);if (!isExist) {return;}//获取队列中的商品,取List中的一个,从右边出来一个,如果能够获取,则商品存在,可以下单String goodsId = (String) redisTemplate.boundListOps(RedisConst.SECKILL_STOCK_PREFIX + skuId).rightPop();if (StringUtils.isEmpty(goodsId)) {//商品售罄,更新状态位  0位售罄状态  发布订阅消息,商品已经销售完了redisTemplate.convertAndSend("seckillpush", skuId+":0");//已售罄return;}//订单记录OrderRecode orderRecode = new OrderRecode();orderRecode.setUserId(userId);orderRecode.setSeckillGoods(this.getSeckillGoods(skuId));orderRecode.setNum(1);//生成订单单码orderRecode.setOrderStr(MD5.encrypt(userId+skuId));//订单数据存入ReidsredisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).put(orderRecode.getUserId(), orderRecode);//更新库存this.updateStockCount(orderRecode.getSeckillGoods().getSkuId());
}

更新库存

//  表示更新mysql -- redis 的库存数据!
public void updateStockCount(Long skuId) {//  加锁!Lock lock = new ReentrantLock();//  上锁lock.lock();try {//  获取到存储库存剩余数!//  key = seckill:stock:46String stockKey = RedisConst.SECKILL_STOCK_PREFIX + skuId;//  redisTemplate.opsForList().leftPush(key,seckillGoods.getSkuId());//获取库存//Long count = this.redisTemplate.boundListOps(RedisConst.SECKILL_STOCK_PREFIX + skuId).size();Long count = redisTemplate.boundListOps(stockKey).size();//  减少库存数!方式一减少压力!//if (count%2==0){//  开始更新数据!SeckillGoods seckillGoods = this.getSeckillGoods(skuId);//  赋值剩余库存数!seckillGoods.setStockCount(count.intValue());//  更新的数据库!seckillGoodsMapper.updateById(seckillGoods);//  更新缓存!redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).put(seckillGoods.getSkuId().toString(),seckillGoods);//}} finally {//  解锁!lock.unlock();}
}
 /*** 获取商品详情* @param skuId* @return*/@Overridepublic SeckillGoods getSeckillGoods(Long skuId) {return (SeckillGoods) this.redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).get(skuId.toString());}

 

减少一个:之前9个 

生成一个订单

用户买过之后生成一个用户的信息(防止多次下单)

(4)页面轮询接口

 

思路:

1.  判断用户是否在缓存中存在

 

2.  判断用户是否抢单成功

3.  判断用户是否下过订单

4.  判断状态位

接口

SeckillGoodsService接口
/**** 根据商品id与用户ID查看订单信息* @param skuId* @param userId* @return*/
Result checkOrder(Long skuId, String userId);

实现类

@Override
public Result checkOrder(Long skuId, String userId) {// 用户在缓存中存在,有机会秒杀到商品boolean isExist =redisTemplate.hasKey(RedisConst.SECKILL_USER + userId);if (isExist) {//判断用户是否正在排队//判断用户是否抢单成功boolean isHasKey = redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).hasKey(userId);if (isHasKey) {//抢单成功  获取用户临时订单:说明还没有支付OrderRecode orderRecode = (OrderRecode) redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).get(userId);// 秒杀成功! return Result.build(orderRecode, ResultCodeEnum.SECKILL_SUCCESS);}}//判断是否下单,查询总订单 seckill:orders:users userId OrderIdboolean isExistOrder = redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS_USERS).hasKey(userId);if(isExistOrder) {String orderId = (String)redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS_USERS).get(userId);return Result.build(orderId, ResultCodeEnum.SECKILL_ORDER_SUCCESS);}String state = (String) CacheHelper.get(skuId.toString());if("0".equals(state)) {//已售罄 抢单失败return Result.build(null, ResultCodeEnum.SECKILL_FAIL);}//正在排队中return Result.build(null, ResultCodeEnum.SECKILL_RUN);
}

控制器

SeckillGoodsApiController
@GetMapping(value = "auth/checkOrder/{skuId}")
public Result checkOrder(@PathVariable("skuId") Long skuId, HttpServletRequest request) {//当前登录用户String userId = AuthContextHolder.getUserId(request);return seckillGoodsService.checkOrder(skuId, userId);
}

 

 

 

轮询排队页面

该页面有四种状态:

  1. 排队中
  2. 各种提示(非法、已售罄等)
  3. 抢购成功,去下单
  4. 抢购成功,已下单,显示我的订单

抢购成功,页面显示去下单,跳转下单确认页面

<div class="seckill_dev" v-if="show == 3">抢购成功&nbsp;&nbsp;<a href="/seckill/trade.html" target="_blank">去下单</a>
</div>

总结:

商品秒杀流程:

1.用户抢单的时候先会生成一个下单码,后面会先校验用户的下单码,只有正确获得下单码的请求才是合法请求,然后再校验状态位state,状态位是在内存中判断,效率极高,如果售罄,直接就返回了,不会给服务器造成太大压力,前面条件都成立,将秒杀用户加入队列,然后直接返回

2.监听队列,进行清单,首先判断产品状态位,我们前面不是已经判断过了吗?因为产品可能随时售罄,mq队列里面可能堆积了十万数据,但是已经售罄了,那么后续流程就没有必要再走了

然后判断用户是否已经下过订单,这个地方就是控制用户重复下单,同一个用户只能抢购一个下单资格,我们可以利用setnx控制用户,当用户第一次进来时,返回true,可以抢购,以后进入返回false

要控制库存数量,不能超卖,提供一种解决方案,那就我们在导入商品缓存数据时,同时将商品库存信息导入队列{list},利用redis队列的原子性,保证库存不超卖

然后将订单记录放入redis缓存,说明用户已经获得下单资格,秒杀成功,秒杀成功要更新库存(更新Mysql的库存和Redis中的库存)

3.前端页面轮训查询订单状态,判断用户是否抢单成功,下单了Redis生成临时订单数据(支付了会删除临时订单)抢单成功,去下单页面,判断用户是否下单查询总订单数据是否支付,下单了去我们订单页面,判断状态位,是否售罄

http://www.dt0577.cn/news/28594.html

相关文章:

  • 个人做网站外包价格如何算怎么做百度关键词排名
  • 上海专业网站建设公杭州网站定制
  • m网购物商城google seo怎么做
  • 高端公司网站建设苏州seo怎么做
  • 博物馆网站 建设方案志鸿优化网官网
  • 易网做的网站后台培训心得总结怎么写
  • 怎么用phpstudy做网站如何自己做网页
  • 湖北建设厅网站谷歌广告
  • 网站商城功能互联网营销师报考条件
  • 新蔡哪有做网站建设的济南seo外包公司
  • 网购网站开发背景如何开发自己的小程序
  • 如何提高网站访客数百度收藏夹使用方法
  • 深圳装修公司排名100强厦门seo推广
  • 淘宝做网站的公司建立营销型网站
  • 做商城网站的公司seo外链发布平台有哪些
  • 做网站的公司挣钱吗青岛网站设计
  • 微信小程序用什么开发工具郑州百度关键词seo
  • 具有营销型网站的公司简述seo的基本步骤
  • 沈阳谷歌网站建设市场营销策划方案范文
  • 济南网站建设用途seo实战密码第三版pdf
  • 无锡那家网络公司做网站好种子搜索在线 引擎
  • 做360网站优化快速seo接单平台
  • win7 做服务器开网站程序员培训机构哪家好
  • 推广网站详细教程接单平台
  • 阿里巴巴怎么建设网站百度投放广告联系谁
  • 西昌直销网站开发央视新闻今天的内容
  • 设计公司推荐seo网站优化网站编辑招聘
  • 做网站运营有前途天眼查询个人
  • 网站域名被劫持户外广告
  • 哪有做网站公司互联网营销推广渠道