java代码优化方案5(秒杀接口地址隐藏)

news/2024/11/10 1:28:27

目录

  • 前言
    • 第一次请求
    • 第二次请求
    • 第三次请求
  • 后言

前言

书接上文,上面的两个章节后我们都知道秒杀的一个业务处理该如何去优化,

java代码优化方案3(redis预减库存,redis标记商品)
java代码优化方案4(Rabbitmq异步下单)

当然也仅仅就是后台对性能的一个优化,本次的话就是结合后台redis缓存的机制和前台多次请求来隐藏自己的接口。

怎么叫多次请求呢?其实就是你操作起来可能就一次请求,可实际上。。。
1、发送请求到后台动态获取一个地址(并redis保存),前台接收地址(path)。

2、在第一次请求成功后会调用第二次请求,第二次请求(我们上两章的内容)携带了path作为我们的路径(redis判断),等处理业务过后,虽然我们会知道后台是否处理成功,但是我们无法知道秒杀是否成功!!(Rabbitmq的原因)

3、第二次请求成功响应过后发送最后第三次请求,用来判断这个用户的这个商品是否成功秒杀

所以我会从三次请求来讲这个借口地址隐藏。
在这里插入图片描述


第一次请求

getMiaoshaPath

function getMiaoshaPath(){
	var goodsId = $("#goodsId").val();
	g_showLoading();
	$.ajax({
		url:"/miaosha/path",
		type:"GET",
		data:{
			goodsId:goodsId,
			verifyCode:$("#verifyCode").val()
		},
		success:function(data){
			if(data.code == 0){
				var path = data.data;
				doMiaosha(path);
			}else{
				layer.msg(data.msg);
			}
		},
		error:function(){
			layer.msg("客户端请求有误");
		}
	});
}

getMiaoshaPath

/**第二阶段
	 * 生成秒杀地址,把秒杀的时间数字传过来
	 * @param request
	 * @param user
	 * @param goodsId
	 * @param verifyCode
	 * @return
	 */
	@RequestMapping(value="/path", method=RequestMethod.GET)
	@ResponseBody
	public Result<String> getMiaoshaPath(HttpServletRequest request, HttpServletResponse response, MiaoshaUser user,
										 @RequestParam("goodsId")long goodsId,
										 @RequestParam(value="verifyCode", defaultValue="0")int verifyCode
	) {
		if(user == null) {//判断用户是否有cookie
			return Result.error(CodeMsg.SESSION_ERROR);
		}
		boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);//(vc)判断这个验证码是否正确,获取redis中的数据
		if(!check) {
			return Result.error(CodeMsg.REQUEST_ILLEGAL);
		}
		String path  =miaoshaService.createMiaoshaPath(user, goodsId);//(mp) 生成一个地址,并存储在redis中
		return Result.success(path);
	}

前台请求:
在这里插入图片描述
后台:
在这里插入图片描述

第二次请求

doMiaosha

function doMiaosha(path){
    $.ajax({
        url:"/miaosha/"+path+"/do_miaosha",
        type:"POST",
        data:{
            goodsId:$("#goodsId").val()
        },
        success:function(data){
            if(data.code == 0){
                //window.location.href="/order_detail.htm?orderId="+data.data.id;
                getMiaoshaResult($("#goodsId").val());
            }else{
                layer.msg(data.msg);
            }
        },
        error:function(){
            layer.msg("客户端请求有误");
        }
    });

}

miaosha

/**第二阶段
	 * QPS:1306
	 * 5000 * 10
	 * QPS: 2114
	 *
	 * 隐藏原有的秒杀地址
	 * */
	@RequestMapping(value="/{path}/do_miaosha", method=RequestMethod.POST)
	@ResponseBody
	public Result<Integer> miaosha(HttpServletRequest request, HttpServletResponse response,
								   Model model,MiaoshaUser user,
								   @RequestParam("goodsId")long goodsId,
								   @PathVariable("path") String path) {
		model.addAttribute("user", user);
		if(user == null) {
			return Result.error(CodeMsg.SESSION_ERROR);
		}
		//1、验证path
		boolean check = miaoshaService.checkPath(user, goodsId, path);//(mp)判断传过来的地址,获取redis中的数据
		if(!check){
			return Result.error(CodeMsg.REQUEST_ILLEGAL);
		}
		//2、内存标记,减少redis访问
		boolean over = localOverMap.get(goodsId);
		if(over) {
			return Result.error(CodeMsg.MIAO_SHA_OVER);
		}
		//3、预减库存
		long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, ""+goodsId);//10
		if(stock < 0) {
			localOverMap.put(goodsId, true);
			redisService.set(MiaoshaKey.isGoodsOver, ""+goodsId, true);//商品库存设置为空
			return Result.error(CodeMsg.MIAO_SHA_OVER);
		}
		//4、判断是否已经秒杀到了
		MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
		if(order != null) {
			return Result.error(CodeMsg.REPEATE_MIAOSHA);
		}
		//入队
		MiaoshaMessage mm = new MiaoshaMessage();
		mm.setUser(user);
		mm.setGoodsId(goodsId);
		sender.sendMiaoshaMessage(mm);
		return Result.success(0);//排队中
    	
	}

前台:
在这里插入图片描述
后台:
在这里插入图片描述

重点:
其实按照我们以前的套路来说,其实在这个请求就已经结束了,因为以前我们的基本业务都在这个请求里面,
可是就是因为我们使用了rabbitmq去异步处理下单的这个业务,所以我们在这个请求的返回结果中是无法直接的获取到秒杀是否成功!!

但是异步处理就是说这个下单的业务处理就完全从那个线程去除掉了。那提高的性能不言而喻。
可是至于另外线程完成的事,我们并不了解,只能通过某个标识来确定是否秒杀过。
在这里插入图片描述


第三次请求

getMiaoshaResult

function getMiaoshaResult(goodsId){
	g_showLoading();
	$.ajax({
		url:"/miaosha/result",
		type:"GET",
		data:{
			goodsId:$("#goodsId").val(),
		},
		success:function(data){
			if(data.code == 0){
				var result = data.data;
				if(result < 0){
					layer.msg("对不起,秒杀失败");
				}else if(result == 0){//继续轮询
					setTimeout(function(){
						getMiaoshaResult(goodsId);
					}, 200);
				}else{
					layer.confirm("恭喜你,秒杀成功!查看订单?", {btn:["确定","取消"]},
							function(){
								window.location.href="/order_detail.htm?orderId="+result;
							},
							function(){
								layer.closeAll();
							});
				}
			}else{
				layer.msg(data.msg);
			}
		},
		error:function(){
			layer.msg("客户端请求有误");
		}
	});
}

miaoshaResult

/**第二阶段
	 * orderId:成功
	 * -1:秒杀失败
	 * 0: 排队中
	 * */
	@RequestMapping(value="/result", method=RequestMethod.GET)
	@ResponseBody
	public Result<Long> miaoshaResult(HttpServletRequest request, HttpServletResponse response,Model model,MiaoshaUser user,
									  @RequestParam("goodsId")long goodsId) {
		model.addAttribute("user", user);
		if(user == null) {
			return Result.error(CodeMsg.SESSION_ERROR);
		}
		long result = miaoshaService.getMiaoshaResult(user.getId(), goodsId);//(moug) 判断是否已经秒杀
		return Result.success(result);
	}

前台
在这里插入图片描述
是否存在的一个判断
在这里插入图片描述
后台:
在这里插入图片描述

后言

重点是要了解这个借口地址是如何获取的,

其次是要判断的一个获取是否还有库存

项目代码:
链接:https://pan.baidu.com/s/1lLuT_BdfpdYxuKSGe_TQqw
提取码:iqeb


http://www.niftyadmin.cn/n/3725571.html

相关文章

【面试必考点】这一次带你彻底学会this的指向问题

文章目录 前言一、this的指向问题1.1 全局中的this1.2 普通函数中的this1.3 定时器中的this1.4 事件处理函数中的this1.5 构造函数中的this1.6 构造函数静态方法中的this1.7 箭头函数中的this 二、修改函数中的this指向2.1 call2.2 apply2.3 bind 三、 this指向练习3.1 某小游戏…

深入Windows NT/2000模块的组织(http://webcrazy.yeah.net)

深入Windows NT/2000模块的组织 WebCrazy( http://webcrazy.yeah.net/)在《 小议Windows NT/2000分页机制 》中我对x86平台Windows NT/2000的非分页内存内部机制有了较为详细的说明&#xff0c;从中也可以看出地址空间可以分为进程空间与系统空间&#xff0c;其中每个进程有各…

自行车运动水壶及水壶架的作用

自行车运动水壶的特点在于可以单手开启&#xff08;徒步及登山用水壶则需要双手开启&#xff09;&#xff0c;这对于喜欢边骑边喝水的朋友比较实用&#xff0c;不过这时要记得放慢速度并注意前后来车哦。水壶架通常安装在车架上&#xff0c;水壶置于其上可以减轻背负重量。 【…

mysql导出数据1049_mysql怎么导入数据库 1049 42000 unknown database

前很多年, 使用mysqldump / mysql 进行数据库的备份和恢复, 都非常成功,但是, 这周换了windows2012 r2 和 mysql 5.6.15后, 并加一个discuz论坛是可以访问的 备份数据库是没有问题的, 但数据库恢复有两个错误:1 测试1命令行 .\mysql -uroot -p 数据库名错误提示内容…

剖析Windows NT/2000内核对象组织(http://webcrazy.yeah.net)

剖析Windows NT/2000内核对象组织 WebCrazy( http://webcrazy.yeah.net/)对象管理器在Windows NT/2000内核中占了极其重要的位置&#xff0c;其一个最主要职能是组织管理系统内核对象。在Windows NT/2000中&#xff0c;内核对象管理器大量引入了C面向对象的思想&#xff0c;即…

mysql 事务处理 存储过程_MySQL存储过程事务处理

Dev tdxDBTreeView可以快速的用tree展示层次结构,无需任何编码;对tree的操作会自动post到数据集:对数据集的操作会 在tree上表现 一.关键 设置 datasource displayField:节点的 ...《JavaScript DOM 编程艺术(第2版)》读书笔记阅读了本书第五章关于使用JavaScript的最佳实践,…

分析Windows NT/2000堆内存与虚拟内存组织(http://webcrazy.yeah.net)

分析Windows NT/2000堆内存与虚拟内存组织 WebCrazy( http://webcrazy.yeah.net/)在讨论今天这个主题时,我觉得是应该给大家重复推介以下两本书:Matt Pietrek<<Windows 95 System Programming Secrets>>Jeffrey Richter<<Programming Microsoft Windows,f…

mysql 三个关联_MySQL中三种关联查询方式的简单比较

看看下面三个关联查询的 SQL 语句有何区别&#xff1f;SELECT * FROM film JOIN film_actor ON (film.film_id film_actor.film_id)SELECT * FROM film JOIN film_actor USING (film_id)SELECT * FROM film, film_actor WHERE film.film_id film_actor.film_id最大的不同更多…