package com.seckill.dis.gateway.seckill;
import com.seckill.dis.common.api.cache.RedisServiceApi;
import com.seckill.dis.common.api.cache.vo.GoodsKeyPrefix;
import com.seckill.dis.common.api.cache.vo.OrderKeyPrefix;
import com.seckill.dis.common.api.cache.vo.SkKeyPrefix;
import com.seckill.dis.common.api.goods.GoodsServiceApi;
import com.seckill.dis.common.api.goods.vo.GoodsVo;
import com.seckill.dis.common.api.mq.MqProviderApi;
import com.seckill.dis.common.api.mq.vo.SkMessage;
import com.seckill.dis.common.api.order.OrderServiceApi;
import com.seckill.dis.common.api.seckill.SeckillServiceApi;
import com.seckill.dis.common.api.seckill.vo.VerifyCodeVo;
import com.seckill.dis.common.api.user.vo.UserVo;
import com.seckill.dis.common.domain.SeckillOrder;
import com.seckill.dis.common.result.CodeMsg;
import com.seckill.dis.common.result.Result;
import com.seckill.dis.common.util.MD5Util;
import com.seckill.dis.common.util.UUIDUtil;
import com.seckill.dis.common.util.VerifyCodeUtil;
import com.seckill.dis.gateway.config.access.AccessLimit;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 秒杀接口
*
* @author mata
*/
@Controller
@RequestMapping("/seckill/")
public class SeckillController implements InitializingBean {
private static Logger logger = LoggerFactory.getLogger(SeckillController.class);
@Reference(interfaceClass = RedisServiceApi.class)
RedisServiceApi redisService;
@Reference(interfaceClass = GoodsServiceApi.class)
GoodsServiceApi goodsService;
@Reference(interfaceClass = SeckillServiceApi.class)
SeckillServiceApi seckillService;
@Reference(interfaceClass = OrderServiceApi.class)
OrderServiceApi orderService;
@Reference(interfaceClass = MqProviderApi.class)
MqProviderApi sender;
/**
* 用于内存标记,标记库存是否为空,从而减少对redis的访问
*/
private Map<Long, Boolean> localOverMap = new HashMap<>();
/**
* 获取秒杀接口地址
* 1. 每一次点击秒杀,都会生成一个随机的秒杀地址返回给客户端
* 2. 对秒杀的次数做限制(通过自定义拦截器注解完成)
*
* @param model
* @param user
* @param goodsId 秒杀的商品id
* @param verifyCode 验证码
* @return 被隐藏的秒杀接口路径
*/
@AccessLimit(seconds = 5, maxAccessCount = 5, needLogin = true)
@RequestMapping(value = "path", method = RequestMethod.GET)
@ResponseBody
public Result<String> getSeckillPath(Model model, UserVo user,
@RequestParam("goodsId") long goodsId,
@RequestParam(value = "verifyCode") int verifyCode) {
/** 在执行下面的逻辑之前,会先对path请求进行拦截处理(@AccessLimit, AccessInterceptor),防止访问次数过于频繁,对服务器造成过大的压力 */
model.addAttribute("user", user);
if (goodsId <= 0) {
return Result.error(CodeMsg.SECKILL_PARM_ILLEGAL.fillArgs("商品id小于0"));
}
// 校验验证码
boolean check = this.checkVerifyCode(user, goodsId, verifyCode);
if (!check)
return Result.error(CodeMsg.VERITF_FAIL);// 检验不通过,请求非法
// 检验通过,获取秒杀路径
String path = this.createSkPath(user, goodsId);
// 向客户端回传随机生成的秒杀地址
return Result.success(path);
}
/* 压力测试时候注释掉 :验证码和秒杀地址隐藏 */
// /**
// * 秒杀逻辑(页面静态化分离,不需要直接将页面返回给客户端,而是返回客户端需要的页面动态数据,返回数据时json格式)
// * <p>
// * QPS:1306
// * 5000 * 10
// * <p>
// * GET/POST的@RequestMapping是有区别的
// * <p>
// * 通过随机的path,客户端隐藏秒杀接口
// * <p>
// * 优化: 不同于每次都去数据库中读取秒杀订单信息,而是在第一次生成秒杀订单成功后,
// * 将订单存储在redis中,再次读取订单信息的时候就直接从redis中读取
// *
// * @param model
// * @param user
// * @param goodsId
// * @param path 隐藏的秒杀地址,为客户端回传的path,最初也是有服务端产生的
// * @return 订单详情或错误码
// */
// // {path}为客户端回传的path,最初也是有服务端产生的
// @RequestMapping(value = "{path}/doSeckill", method = RequestMethod.POST)
// @ResponseBody
// public Result<Integer> doSeckill(Model model, UserVo user,
// @RequestParam("goodsId") long goodsId,
// @PathVariable("path") String path) {
// model.addAttribute("user", user);
// // 验证path是否正确
// boolean check = this.checkPath(user, goodsId, path);
// if (!check)
// return Result.error(CodeMsg.REQUEST_ILLEGAL);// 请求非法
// // 通过内存标记,减少对redis的访问,秒杀未结束才继续访问redis
// Boolean over = localOverMap.get(goodsId);
// if (over)
// return Result.error(CodeMsg.SECKILL_OVER);
// // 预减库存,同时在库存为0时标记该商品已经结束秒杀
// Long stock = redisService.decr(GoodsKeyPrefix.GOODS_STOCK, "" + goodsId);
// if (stock < 0) {
// localOverMap.put(goodsId, true);// 秒杀结束。标记该商品已经秒杀结束
// return Result.error(CodeMsg.SECKILL_OVER);
// }
// // 判断是否重复秒杀
// // 从redis中取缓存,减少数据库的访问
// SeckillOrder order = redisService.get(OrderKeyPrefix.SK_ORDER, ":" + user.getUuid() + "_" + goodsId, SeckillOrder.class);
// // 如果缓存中不存该数据,则从数据库中取
// if (order == null) {
// order = orderService.getSeckillOrderByUserIdAndGoodsId(user.getUuid(), goodsId);
// }
// if (order != null) {
// return Result.error(CodeMsg.REPEATE_SECKILL);
// }
// // 商品有库存且用户为秒杀商品,则将秒杀请求放入MQ
// SkMessage message = new SkMessage();
// message.setUser(user);
// message.setGoodsId(goodsId);
// // 放入MQ(对秒杀请求异步处理,直接返回)
// sender.sendSkMessage(message);
// // 排队中
// return Result.success(0);
// }
/**
* 秒杀逻辑(页面静态化分离,不需要直接将页面返回给客户端,而是返回客户端需要的页面动态数据,返回数据时json格式)
* <p>
* QPS:1117
* 5000 * 10
* <p>
* GET/POST的@RequestMapping是有区别的
* <p>
* 通过随机的path,客户端隐藏秒杀接口
* <p>
* 优化: 不同于每次都去数据库中读取秒杀订单信息,而是在第一次生成秒杀订单成功后,
* 将订单存储在redis中,再次读取订单信息的时候就直接从redis中读取
*
* @param model
* @param user
* @param goodsId
* @return 订单详情或错误码
*/
// 秒杀压力测试时接口
@RequestMapping(value = "doSeckill", method = RequestMethod.POST)
@ResponseBody
public Result<Integer> doSeckill( UserVo user,
@RequestPara
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
【资源介绍】 基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统.zip 【备注】 该项目是个人毕设项目,答辩评审分达到95分,代码都经过调试测试,确保可以运行!欢迎下载使用,可用于小白学习、进阶。 该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。 项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 欢迎下载,欢迎沟通,互相学习,共同进步!提供答疑!
资源推荐
资源详情
资源评论
收起资源包目录
基于SpringBoot+Zookeeper+Dubbo打造分布式高并发商品秒杀系统源码.zip (146个子文件)
bootstrap.css 143KB
bootstrap.min.css 118KB
bootstrap-theme.css 26KB
bootstrap-theme.min.css 23KB
layer.css 14KB
layer.css 5KB
glyphicons-halflings-regular.eot 20KB
loading-0.gif 6KB
loading-2.gif 2KB
loading-1.gif 701B
.gitignore 1KB
order_detail.htm 4KB
goods_detail.htm 3KB
register.html 6KB
login.html 4KB
goods_detail.html 4KB
order_detail.html 3KB
goods_list.html 3KB
SeckillController.java 15KB
UserServiceImpl.java 7KB
AccessInterceptor.java 7KB
SeckillServiceImpl.java 6KB
GoodsController.java 6KB
UserUtil.java 6KB
UserArgumentResolver.java 6KB
RedisServiceImpl.java 5KB
UserController.java 4KB
OrderServiceImpl.java 3KB
CodeMsg.java 3KB
MD5Util.java 3KB
MqConsumer.java 3KB
OrderInfo.java 3KB
VerifyCodeUtil.java 3KB
UserInfoVo.java 3KB
GlobalExceptionHandler.java 3KB
RedisLockImpl.java 2KB
GlobalExceptionHandler.java 2KB
UserVo.java 2KB
SeckillUser.java 2KB
SeckillUser.java 2KB
OrderController.java 2KB
MqProviderImpl.java 2KB
Result.java 2KB
OrderMapper.java 2KB
JsonUtil.java 2KB
UserServiceApi.java 2KB
WebConfig.java 2KB
IsMobileValidator.java 2KB
GoodsServiceImpl.java 1KB
GoodsMapper.java 1KB
RedisServiceApi.java 1KB
Goods.java 1KB
RedisConfig.java 1KB
DBUtil.java 1KB
GoodsVo.java 1KB
GoodsDetailVo.java 1KB
MQConfig.java 1KB
SeckillGoods.java 1KB
RegisterVo.java 1KB
LoginVo.java 1KB
GoodsKeyPrefix.java 1KB
BaseKeyPrefix.java 1KB
SkKeyPrefix.java 1007B
IsMobile.java 1001B
OrderDetailVo.java 954B
SeckillServiceApi.java 942B
OrderServiceApi.java 934B
RedisPoolFactory.java 891B
SeckillUserMapper.java 874B
VerifyCodeVo.java 850B
SkMessage.java 821B
ValidatorUtil.java 817B
SeckillOrder.java 813B
GoodsServiceApi.java 805B
AccessLimit.java 767B
DLockApi.java 729B
UserContext.java 681B
SkUserKeyPrefix.java 661B
OrderKeyPrefix.java 628B
AccessKeyPrefix.java 561B
UserApplication.java 511B
GlobalException.java 464B
GlobalException.java 463B
KeyPrefix.java 445B
UserKey.java 380B
GatewayApplication.java 375B
GoodsApplication.java 367B
OrderApplication.java 367B
MqApplication.java 365B
CacheApplication.java 347B
MqProviderApi.java 345B
UUIDUtil.java 256B
秒杀测试.jmx 11KB
bg2.jpg 80KB
jquery.min.js 82KB
bootstrap.js 68KB
bootstrap.min.js 36KB
layer.js 21KB
jquery.validate.min.js 21KB
additional-methods.min.js 17KB
共 146 条
- 1
- 2
资源评论
z同学的编程之路
- 粉丝: 1865
- 资源: 2130
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 论文(最终)_20240430235101.pdf
- 基于python编写的Keras深度学习框架开发,利用卷积神经网络CNN,快速识别图片并进行分类
- 最全空间计量实证方法(空间杜宾模型和检验以及结果解释文档).txt
- 5uonly.apk
- 蓝桥杯Python组的历年真题
- 2023-04-06-项目笔记 - 第一百十九阶段 - 4.4.2.117全局变量的作用域-117 -2024.04.30
- 2023-04-06-项目笔记 - 第一百十九阶段 - 4.4.2.117全局变量的作用域-117 -2024.04.30
- 前端开发技术实验报告:内含4四实验&实验报告
- Highlight Plus v20.0.1
- 林周瑜-论文.docx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功