miaosha/miaosha-v1/src/main/java/com/geekq/miaosha/controller/MiaoshaController.java

218 lines
8.1 KiB
Java
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.geekq.miaosha.controller;
import com.geekq.miaosha.access.AccessLimit;
import com.geekq.miaosha.common.resultbean.ResultGeekQ;
import com.geekq.miaosha.domain.MiaoshaOrder;
import com.geekq.miaosha.domain.MiaoshaUser;
import com.geekq.miaosha.rabbitmq.MQSender;
import com.geekq.miaosha.rabbitmq.MiaoshaMessage;
import com.geekq.miaosha.redis.GoodsKey;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.service.GoodsService;
import com.geekq.miaosha.service.MiaoShaUserService;
import com.geekq.miaosha.service.MiaoshaService;
import com.geekq.miaosha.service.OrderService;
import com.geekq.miaosha.vo.GoodsVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import static com.geekq.miaosha.common.enums.ResultStatus.*;
@Controller
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean {
private static Logger logger = LoggerFactory.getLogger(MiaoshaController.class);
@Autowired
MiaoShaUserService userService;
@Autowired
RedisService redisService;
@Autowired
GoodsService goodsService;
@Autowired
OrderService orderService;
@Autowired
MiaoshaService miaoshaService;
@Autowired
MQSender mqSender;
private HashMap<Long, Boolean> localOverMap = new HashMap<Long, Boolean>();
/**
* QPS:1306
* 5000 * 10
* get post get 幂等 从服务端获取数据 不会产生影响  post 对服务端产生变化
*/
@AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
@RequestMapping(value="/{path}/do_miaosha", method= RequestMethod.POST)
@ResponseBody
public ResultGeekQ<Integer> miaosha(Model model, MiaoshaUser user, @PathVariable("path") String path,
@RequestParam("goodsId") long goodsId) {
ResultGeekQ<Integer> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
//验证path
boolean check = miaoshaService.checkPath(user, goodsId, path);
if (!check) {
result.withError(REQUEST_ILLEGAL.getCode(), REQUEST_ILLEGAL.getMessage());
return result;
}
// //使用RateLimiter 限流
// RateLimiter rateLimiter = RateLimiter.create(10);
// //判断能否在1秒内得到令牌如果不能则立即返回false不会阻塞程序
// if (!rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
// System.out.println("短期无法获取令牌,真不幸,排队也瞎排");
// return ResultGeekQ.error(CodeMsg.MIAOSHA_FAIL);
//
// }
//是否已经秒杀到
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(Long.valueOf(user.getNickname()), goodsId);
if (order != null) {
result.withError(REPEATE_MIAOSHA.getCode(), REPEATE_MIAOSHA.getMessage());
return result;
}
//内存标记减少redis访问
boolean over = localOverMap.get(goodsId);
if (over) {
result.withError(MIAO_SHA_OVER.getCode(), MIAO_SHA_OVER.getMessage());
return result;
}
//预见库存
Long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, "" + goodsId);
if (stock < 0) {
localOverMap.put(goodsId, true);
result.withError(MIAO_SHA_OVER.getCode(), MIAO_SHA_OVER.getMessage());
return result;
}
MiaoshaMessage mm = new MiaoshaMessage();
mm.setGoodsId(goodsId);
mm.setUser(user);
mqSender.sendMiaoshaMessage(mm);
return result;
}
/**
* orderId成功
* -1秒杀失败
* 0 排队中
*/
@AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
@RequestMapping(value = "/result", method = RequestMethod.GET)
@ResponseBody
public ResultGeekQ<Long> miaoshaResult(Model model, MiaoshaUser user,
@RequestParam("goodsId") long goodsId) {
ResultGeekQ<Long> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
model.addAttribute("user", user);
Long miaoshaResult = miaoshaService.getMiaoshaResult(Long.valueOf(user.getNickname()), goodsId);
result.setData(miaoshaResult);
return result;
}
@AccessLimit(seconds = 5, maxCount = 5, needLogin = true)
@RequestMapping(value = "/path", method = RequestMethod.GET)
@ResponseBody
public ResultGeekQ<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user,
@RequestParam("goodsId") long goodsId,
@RequestParam(value = "verifyCode", defaultValue = "0") int verifyCode
) {
ResultGeekQ<String> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
if (!check) {
result.withError(REQUEST_ILLEGAL.getCode(), REQUEST_ILLEGAL.getMessage());
return result;
}
String path = miaoshaService.createMiaoshaPath(user, goodsId);
result.setData(path);
return result;
}
@RequestMapping(value = "/verifyCodeRegister", method = RequestMethod.GET)
@ResponseBody
public ResultGeekQ<String> getMiaoshaVerifyCod(HttpServletResponse response
) {
ResultGeekQ<String> result = ResultGeekQ.build();
try {
BufferedImage image = miaoshaService.createVerifyCodeRegister();
OutputStream out = response.getOutputStream();
ImageIO.write(image, "JPEG", out);
out.flush();
out.close();
return result;
} catch (Exception e) {
logger.error("生成验证码错误-----注册:{}", e);
result.withError(MIAOSHA_FAIL.getCode(), MIAOSHA_FAIL.getMessage());
return result;
}
}
@RequestMapping(value = "/verifyCode", method = RequestMethod.GET)
@ResponseBody
public ResultGeekQ<String> getMiaoshaVerifyCod(HttpServletResponse response, MiaoshaUser user,
@RequestParam("goodsId") long goodsId) {
ResultGeekQ<String> result = ResultGeekQ.build();
if (user == null) {
result.withError(SESSION_ERROR.getCode(), SESSION_ERROR.getMessage());
return result;
}
try {
BufferedImage image = miaoshaService.createVerifyCode(user, goodsId);
OutputStream out = response.getOutputStream();
ImageIO.write(image, "JPEG", out);
out.flush();
out.close();
return result;
} catch (Exception e) {
logger.error("生成验证码错误-----goodsId:{}", goodsId, e);
result.withError(MIAOSHA_FAIL.getCode(), MIAOSHA_FAIL.getMessage());
return result;
}
}
/**
* 系统初始化
*
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
List<GoodsVo> goodsList = goodsService.listGoodsVo();
if (goodsList == null) {
return;
}
for (GoodsVo goods : goodsList) {
redisService.set(GoodsKey.getMiaoshaGoodsStock, "" + goods.getId(), goods.getStockCount());
localOverMap.put(goods.getId(), false);
}
}
}