1 在之前的代码中,插入代码,以显示商品列表。
@RequestMapping("to_list")
public String toList(@CookieValue(value= CookieUtil.COOKIE_NAME,required = false) String cookieToken,
@RequestParam(value = CookieUtil.COOKIE_NAME,required = false) String paramToken,
Model model,HttpServletResponse response){
if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)){
return "login";
}
String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
MiaoshaUser user = userService.getByToken(token,response);
model.addAttribute("user",user);
return "goods_list";
}
插入:
//查询商品列表
List<GoodsVo> goodsList = goodsService.listGoodsVo();
model.addAttribute("goodsList", goodsList);
其中goodsService.listGoodsVo()实现如下:
public List<GoodsVo> listGoodsVo(){
return goodsDao.listGoodsVo();
}
goodsDao.listGoodsVo()实现如下:
@Select("select g.*,mg.stock_count, mg.start_date, mg.end_date,mg.miaosha_price
from miaosha_goods mg left join goods g on mg.goods_id = g.id")
public List<GoodsVo> listGoodsVo();
2 这样,登录成功后,跳转到goods_list.html后,就能显示商品列表了
<body>
<div class="panel panel-default">
<div class="panel-heading">秒杀商品列表</div>
<table class="table" id="goodslist">
<tr><td>商品名称</td><td>商品图片</td><td>商品原价</td><td>秒杀价</td><td>库存数量</td><td>详情</td></tr>
<tr th:each="goods,goodsStat : ${goodsList}">
<td th:text="${goods.goodsName}"></td>
<td ><img th:src="@{${goods.goodsImg}}" width="100" height="100" /></td>
<td th:text="${goods.goodsPrice}"></td>
<td th:text="${goods.miaoshaPrice}"></td>
<td th:text="${goods.stockCount}"></td>
<td><a th:href="'/goods/to_detail/'+${goods.id}">详情</a></td>
</tr>
</table>
</div>
</body>
3 可以通过点击商品详情按钮,跳转到’/goods/to_detail/’
<td><a th:href="'/goods/to_detail/'+${goods.id}">详情</a></td>
在’/goods/to_detail/'中
@RequestMapping("/to_detail/{goodsId}")
public String detail(Model model,MiaoshaUser user,
@PathVariable("goodsId")long goodsId) {
model.addAttribute("user", user);
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
model.addAttribute("goods", goods);
long startAt = goods.getStartDate().getTime();
long endAt = goods.getEndDate().getTime();
long now = System.currentTimeMillis();
int miaoshaStatus = 0;
int remainSeconds = 0;
if(now < startAt ) {//秒杀还没开始,倒计时
miaoshaStatus = 0;
remainSeconds = (int)((startAt - now )/1000);
}else if(now > endAt){//秒杀已经结束
miaoshaStatus = 2;
remainSeconds = -1;
}else {//秒杀进行中
miaoshaStatus = 1;
remainSeconds = 0;
}
model.addAttribute("miaoshaStatus", miaoshaStatus);
model.addAttribute("remainSeconds", remainSeconds);
return "goods_detail";
}
对于前端goods_detail.html,只需要拿到这个remainSeconds就可以了,可以对应显示秒杀还剩多久、秒杀是否结束等。
<td id="miaoshaTip">
<input type="hidden" id="remainSeconds" th:value="${remainSeconds}" />
<span th:if="${miaoshaStatus eq 0}">秒杀倒计时:<span id="countDown" th:text="${remainSeconds}"></span>秒</span>
<span th:if="${miaoshaStatus eq 1}">秒杀进行中</span>
<span th:if="${miaoshaStatus eq 2}">秒杀已结束</span>
</td>
<td>
<form id="miaoshaForm" method="post" action="/miaosha/do_miaosha">
<button class="btn btn-primary btn-block" type="submit" id="buyButton">立即秒杀</button>
<input type="hidden" name="goodsId" th:value="${goods.id}" />
</form>
</td>
function countDown(){
var remainSeconds = $("#remainSeconds").val();
var timeout;
if(remainSeconds > 0){//秒杀还没开始,倒计时
$("#buyButton").attr("disabled", true);
timeout = setTimeout(function(){
$("#countDown").text(remainSeconds - 1);
$("#remainSeconds").val(remainSeconds - 1);
countDown();
},1000);
}else if(remainSeconds == 0){//秒杀进行中
$("#buyButton").attr("disabled", false);
if(timeout){
clearTimeout(timeout);
}
$("#miaoshaTip").html("秒杀进行中");
}else{//秒杀已经结束
$("#buyButton").attr("disabled", true);
$("#miaoshaTip").html("秒杀已经结束");
}
}
在倒计时结束后,点击立即秒杀,跳转到"miaosha/do_miaosha"
<form id="miaoshaForm" method="post" action="/miaosha/do_miaosha">
4 在miaosha/do_miaosha实行以下逻辑:
判断库存
|
根据userId和goodsId判断是否已经抢过了
|
减库存,下订单,并且写入秒杀订单(同一事务中完成)
@RequestMapping("/do_miaosha")
public String list(Model model,MiaoshaUser user,
@RequestParam("goodsId")long goodsId) {
model.addAttribute("user", user);
if(user == null) {
return "login";
}
//判断库存
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
int stock = goods.getStockCount();
if(stock <= 0) {
model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
return "miaosha_fail";
}
//判断是否已经秒杀到了
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
if(order != null) {
model.addAttribute("errmsg", CodeMsg.REPEATE_MIAOSHA.getMsg());
return "miaosha_fail";
}
//减库存 下订单 写入秒杀订单
OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
model.addAttribute("orderInfo", orderInfo);
model.addAttribute("goods", goods);
return "order_detail";
}
其中,orderService.getMiaoshaOrderByUserIdGoodsId
public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(long userId, long goodsId) {
return orderDao.getMiaoshaOrderByUserIdGoodsId(userId, goodsId);
}
而,orderDao.getMiaoshaOrderByUserIdGoodsId
@Select("select * from miaosha_order where user_id=#{userId} and goods_id=#{goodsId}")
public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(@Param("userId")long userId, @Param("goodsId")long goodsId);
其中,miaoshaService.miaosha。@Transactional保证在同一个事务中
@Transactional
public OrderInfo miaosha(MiaoshaUser user, GoodsVo goods) {
//减库存 下订单 写入秒杀订单
goodsService.reduceStock(goods);
//order_info maiosha_order
return orderService.createOrder(user, goods);
}
而,goodsService.reduceStock
public void reduceStock(GoodsVo goods) {
MiaoshaGoods g = new MiaoshaGoods();
g.setGoodsId(goods.getId());
goodsDao.reduceStock(g);
}
而,goodsDao.reduceStock
@Update("update miaosha_goods set stock_count = stock_count - 1 where goods_id = #{goodsId}")
public int reduceStock(MiaoshaGoods g);
同时,orderService.createOrder
对于创建订单:先是普通的order_info表插入,还有一个是miaosha_order表插入,那么就要在一个事务中执行。
@Transactional
public OrderInfo createOrder(MiaoshaUser user, GoodsVo goods) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setCreateDate(new Date());
orderInfo.setDeliveryAddrId(0L);
orderInfo.setGoodsCount(1);
orderInfo.setGoodsId(goods.getId());
orderInfo.setGoodsName(goods.getGoodsName());
orderInfo.setGoodsPrice(goods.getMiaoshaPrice());
orderInfo.setOrderChannel(1);
orderInfo.setStatus(0);
orderInfo.setUserId(user.getId());
long orderId = orderDao.insert(orderInfo);
MiaoshaOrder miaoshaOrder = new MiaoshaOrder();
miaoshaOrder.setGoodsId(goods.getId());
miaoshaOrder.setOrderId(orderId);
miaoshaOrder.setUserId(user.getId());
orderDao.insertMiaoshaOrder(miaoshaOrder);
return orderInfo;
}
而,orderDao.insert
@Insert("insert into order_info(user_id,goods_id,goods_name,goods_price,goods_count,order_channel,status,create_date) " +
"values(#{userId},#{goodsId},#{goodsName},#{goodsPrice},#{goodsCount},#{orderChannel},#{status},#{" +
"createDate})")
@SelectKey(keyColumn = "id",keyProperty = "id",resultType = long.class,before = false,statement = "select last_insert_id()")
long insert(OrderInfo orderInfo);
而,orderDao.insertMiaoshaOrder
@Insert("insert into miaosha_order(user_id,goods_id,order_id)values(#{userId},#{goodsId},#{orderId})")
int insertMiaoshaOrder(MiaoshaOrder miaoshaOrder);
下单成功的话,就跳到订单详情页面:
return "order_detail";
否则跳到错误提示页面:
return "miaosha_fail";