methods: {
getSrcUrl(t) {
return getServerUrl('image/' + t);
},
exec_miaosha(){
if(this.verifyCode==""){
alert("请输入验证码结果!");
return;
}
let url = getServerUrl("miaoSha/exec");
let token = window.sessionStorage.getItem("token");
axios.defaults.headers.common['token'] = token;
axios.get(url,{
params:{
miaoShaGoodsId:this.$route.params.id,
verifyCode:this.verifyCode
}
}).then(response=>{
let data = response.data;
this.miaoShaGoods.miaoShaStatus=4;
if(data.code!=0){
alert(data.msg);
this.miaoShaResult=data.msg;
}else{
// alert(data.orderId);
this.miaoShaResult=data.msg;
this.getMiaoShaResult(this.$route.params.id);
}
}).catch(error=>{
alert(error+"-请联系管理员");
})
},
getMiaoShaResult(miaoShaGoodsId){
let url = getServerUrl("miaoSha/result");
let token = window.sessionStorage.getItem("token");
axios.defaults.headers.common['token'] = token;
axios.get(url,{
params:{
miaoShaGoodsId:this.$route.params.id
}
}).then(response=>{
let data = response.data;
if(data.code!=0){
alert(data.msg);
this.miaoShaResult=data.msg;
}else{
let result=data.result;
if(result=="0"){ // 排队中,继续轮询
setTimeout(function (){
this.getMiaoShaResult(miaoShaGoodsId)
},50);
}else if(result=="-1"){
this.miaoShaResult="秒杀失败";
}else{
alert("秒杀成功! ");
alert(result);
}
}
}).catch(error=>{
alert(error+"-请联系管理员");
})
},
package com.java1234.miaosha.service.impl;
import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.mapper.MiaoShaGoodsMapper;
import com.java1234.miaosha.mapper.OrderMapper;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.util.DateUtil;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
/**
* 秒杀Service实现类
*/
@Service("miaoShaService")
public class MiaoShaServiceImpl implements IMiaoShaService {
@Autowired
private MiaoShaGoodsMapper miaoShaGoodsMapper;
@Autowired
private OrderMapper orderMapper;
@Autowired
private RedisUtil redisUtil;
/**
* 如果执行成功,返回订单ID,否则返回Null
* @param user
* @param miaoShaGoodsVo
* @return
*/
@Override
@Transactional
public String miaoSha(User user, MiaoShaGoodsVo miaoShaGoodsVo) {
//库存减1操作
Integer affectedRows = miaoShaGoodsMapper.reduceStock(miaoShaGoodsVo.getId());
if(affectedRows==0){
return null;
}
//生成订单
Order order = new Order();
order.setId(DateUtil.getCurrentDateStr()); //生成订单号
order.setUser(user);
order.setMiaoShaGoods(miaoShaGoodsVo);
order.setCount(1);
order.setTotalPrice(miaoShaGoodsVo.getPrice());
order.setPayMethod(null);
order.setStatus(0);
Integer affectedRows2 = orderMapper.add(order);
if(affectedRows2==0){
return null;
}
return order.getId();
}
@Override
public String getMiaoShaResult(Integer userId, Integer miaoShaGoodsId) {
HashMap map=new HashMap();
map.put("user_id",userId);
map.put("miaosha_goods_id",miaoShaGoodsId);
Order order=orderMapper.findByUserIdAndMiaoShaGoodsId(map);
if(order!=null){
return order.getId();
}else{
// TODO 查询商品是否秒杀完 从redis中判断是否商品秒杀完
boolean isOver = (boolean) redisUtil.get(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX, miaoShaGoodsId + "");
boolean over=true;
if(over){
return "-1";
}else{
return "0";
}
}
}
}
package com.java1234.miaosha.controller;
import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.rabbitmq.MQSender;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.service.IOrderService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.util.StringUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 秒杀控制器
*/
@RestController
@RequestMapping("/miaoSha")
public class MiaoShaController {
@Autowired
private RedisUtil redisUtil;
@Autowired
private IMiaoShaGoodsService miaoShaGoodsService;
@Autowired
private IMiaoShaService miaoShaService;
@Autowired
private IOrderService orderService;
@Autowired
private MQSender mqSender;
/**
* 执行秒杀
* @param request
* @param miaoShaGoodsId
* @return
*/
@RequestMapping("/exec")
public R exec(HttpServletRequest request, Integer miaoShaGoodsId,String verifyCode){
if(StringUtil.isEmpty(verifyCode)){
return R.error("验证码不能为空!");
}
//第一步:根据token得到用户user对象
String token = request.getHeader("token");
System.out.println("token:"+token);
User user = (User)redisUtil.get(Constant.REDIS_TOKEN_PREFIX, token);
System.out.println(user);
Object rnd=redisUtil.get(Constant.REDIS_VERIFYCODE_PREFIX, user.getId() + "," + miaoShaGoodsId);
if(rnd==null){
return R.error("验证码过期,请重新点击刷新验证码!");
}
if(!verifyCode.equals(String.valueOf(rnd))){
return R.error("验证码结果错误!");
}
boolean isOver = (boolean) redisUtil.get(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX, miaoShaGoodsId + "");
if(isOver){
return R.ok("秒杀结束");
}
long stock = redisUtil.decr(Constant.REDIS_STOCK_PREFIX, miaoShaGoodsId + "", 1);
if(stock<0){
return R.error("秒杀失败,商品已经秒光,欢迎参与!");
}
MiaoShaMessage mm=new MiaoShaMessage();
mm.setUser(user);
mm.setMiaoShaGoodsId(miaoShaGoodsId);
mqSender.sendMiaoShaMessage(mm);
return R.ok("排队中");
// //第二步:判断库存是否足够
// MiaoShaGoodsVo miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId);
// Integer stock = miaoShaGoods.getStock();
// if(stock<=0){
// return R.error("库存不足!");
// }
//
// //第三步:判断用户是否重复秒杀
// HashMap map = new HashMap();
// map.put("user_id",user.getId());
// map.put("miaosha_goods_id",miaoShaGoodsId);
// Order orderE = orderService.findByUserIdAndMiaoShaGoodsId(map);
// if(orderE!=null){
// return R.error("您已经秒杀过此商品,不能重复秒杀");
// }
//
// //第四步:减库存,下订单,必须同一个事务
// String orderId = miaoShaService.miaoSha(user, miaoShaGoods);
// if(orderId!=null){
// Map<String,Object> resultMap=new HashMap<>();
// resultMap.put("orderId",orderId);
// return R.ok(resultMap);
// }else{
// return R.error("系统异常,请稍后重试!");
// }
}
/**
* 秒杀结果查询
* @param request
* @param miaoShaGoodsId
* @return >0 返回orderId 订单ID -1 秒杀失败 0 排队中
*/
@RequestMapping("/result")
public R result(HttpServletRequest request,Integer miaoShaGoodsId){
String token = request.getHeader("token");
System.out.println("token:"+token);
User user = (User)redisUtil.get(Constant.REDIS_TOKEN_PREFIX, token);
System.out.println(user);
String result=miaoShaService.getMiaoShaResult(user.getId(),miaoShaGoodsId);
Map<String,Object> resultMap=new HashMap<>();
resultMap.put("result",result);
return R.ok(resultMap);
}
}
package com.java1234.miaosha.rabbitmq;
import com.java1234.miaosha.config.MQConfig;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.util.BeanUtil;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MQSender {
@Autowired
private AmqpTemplate amqpTemplate;
public void sendMiaoShaMessage(MiaoShaMessage miaoShaMessage){
String msg = BeanUtil.beanToString(miaoShaMessage);
System.out.println("send message:"+msg);
amqpTemplate.convertAndSend(MQConfig.MIAOSHA_QUEUE,msg);
}
}
package com.java1234.miaosha.run;
import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 启动的时候加载加载秒杀商品库存信息和是否秒杀完成标识
*/
@Component("startupRunner")
public class StartupRunner implements CommandLineRunner {
@Autowired
private IMiaoShaGoodsService miaoShaGoodsService;
@Autowired
private RedisUtil redisUtil;
@Override
public void run(String... args) throws Exception {
List<MiaoShaGoodsVo> miaoShaGoodsVoList = miaoShaGoodsService.listAll();
System.out.println("启动加载秒杀库存信息");
for(MiaoShaGoodsVo miaoShaGoodsVo:miaoShaGoodsVoList){
System.out.println(miaoShaGoodsVo.getId()+":"+miaoShaGoodsVo.getStock());
redisUtil.set2(Constant.REDIS_STOCK_PREFIX,miaoShaGoodsVo.getId()+"",miaoShaGoodsVo.getStock()+"");
redisUtil.set(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX,miaoShaGoodsVo.getId()+"",false);
}
}
}
package com.java1234.miaosha.rabbitmq;
import com.java1234.miaosha.config.MQConfig;
import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.service.IOrderService;
import com.java1234.miaosha.util.BeanUtil;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@Service
public class MQReceiver {
@Autowired
private RedisUtil redisUtil;
@Autowired
private IMiaoShaGoodsService miaoShaGoodsService;
@Autowired
private IMiaoShaService miaoShaService;
@Autowired
private IOrderService orderService;
@RabbitListener(queues = MQConfig.MIAOSHA_QUEUE)
public void receiveMiaoShaMessage(String message){
MiaoShaMessage miaoShaMessage = BeanUtil.stringToBean(message, MiaoShaMessage.class);
System.out.println("receive message:"+miaoShaMessage);
User user = miaoShaMessage.getUser();
Integer miaoShaGoodsId=miaoShaMessage.getMiaoShaGoodsId();
//第二步:判断库存是否足够
MiaoShaGoodsVo miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId);
Integer stock = miaoShaGoods.getStock();
if(stock<=0){
redisUtil.set(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX,miaoShaGoodsId+"",true);
System.out.println("库存不足");
return;
}
//第三步:判断用户是否重复秒杀
HashMap map = new HashMap();
map.put("user_id",user.getId());
map.put("miaosha_goods_id",miaoShaGoodsId);
Order orderE = orderService.findByUserIdAndMiaoShaGoodsId(map);
if(orderE!=null){
System.out.println("您已经秒杀过此商品,不能重复秒杀");
return;
}
//第四步:减库存,下订单,必须同一个事务
String orderId = miaoShaService.miaoSha(user, miaoShaGoods);
}
}
server:
port: 80
servlet:
context-path: /
spring:
rabbitmq:
host: 192.168.30.113
port: 5672
username: admin
password: admin
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_miaosha3?serverTimezone=Asia/Shanghai
username: root
password: 123456
redis:
host: 192.168.30.113
port: 6379
password:
connect-timeout: 10s
lettuce:
pool:
max-active: 8
max-wait: 200s
max-idle: 8
min-idle: 0
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mybatis/mapper/*.xml