萝岗手机网站建设,wordpress添加版权,一站式网站管家,快印店网站建设84wzjs文章目录 1.显示秒杀状态1.controller修改GoodsController.java的toDetail方法#xff0c;响应秒杀状态和秒杀剩余时间 2.前端1.goodsDetail.html 图片下面添加一行秒杀开始时间2.goodsDetail.html 添加计时器js代码 3.测试1.秒杀进行中2.修改db的秒杀开始时间为明天3.出现秒杀… 文章目录 1.显示秒杀状态1.controller修改GoodsController.java的toDetail方法响应秒杀状态和秒杀剩余时间 2.前端1.goodsDetail.html 图片下面添加一行秒杀开始时间2.goodsDetail.html 添加计时器js代码 3.测试1.秒杀进行中2.修改db的秒杀开始时间为明天3.出现秒杀倒计时4.修改db的秒杀结束时间比目前要早5.秒杀已结束 2.秒杀按钮1.前端1.goodsDetail.html 添加抢购按钮2.goodsDetail.html 根据秒杀状态控制按钮状态 2.测试1.秒杀已结束按钮不可用2.秒杀进行中按钮可用3.秒杀未开始按钮不可用 3.秒杀基本功能不考虑高并发1.数据库表设计1.普通订单表2.秒杀订单表 2.MyBatis-Plus生成基础代码以t_order表为例1.首先 ctrl shift c 复制基础包名一定要是带点的2.右键表名选择 MybatisX-Generator3.选择模块和基础包以及实体类名字4.进行配置5.点击生成检查代码1.整个目录概览2.把实体类移动到pojo并检查3.检查 OrderMapper.java 发现没有加Mapper注解4.查看启动类有MapperScan所以不用加Mapper了5.检查OrderMapper.xml6.检查application.yml是否自动扫描了Mapper.xml7.检查OrderService.java8.检查OrderServiceImpl.java 6.使用MyBatis-Plus生成基础代码的小结7.以同样的方式生成t_seckill_order 3.Service层1.OrderService.java 新增秒杀方法返回订单2.OrderServiceImpl.java3.SeckillOrderService.java 根据普通订单和商品id插入秒杀订单4.SeckillOrderServiceImpl.java 4.Controller层1.SeckillController.java 完成基础版本的秒杀简单考虑库存和复购问题2.SeckillOrderService.java 新增方法根据用户id和商品id查找记录3.SeckillOrderServiceImpl.java4.SeckillOrderMapper.java5.SeckillOrderMapper.xml 5.前端1.goodsDetail.html 修改点击抢购按钮的请求区分多环境2.引入orderDetail.html3.引入secKillFail.html 6.测试1.正常秒杀1.初始秒杀商品表库存为102.秒杀1号商品3.秒杀成功4.秒杀商品库存减15.普通订单新增一条记录6.秒杀订单新增一条记录 2.当前用户再次购买成功跳转到限购页面 3.模拟库存不足的情况1.将1号商品的库存修改为02.切换一个浏览器再次秒杀3.成功跳转到库存不足的页面 1.显示秒杀状态
1.controller
修改GoodsController.java的toDetail方法响应秒杀状态和秒杀剩余时间 // 进入到商品详情页RequestMapping(/toDetail/{goodsId})public String toDetail(Model model, User user, PathVariable Long goodsId) {// 判断是否有用户信息if (null user) {return login;}// 查询商品详情GoodsVo goodsVoByGoodsId goodsService.findGoodsVoByGoodsId(goodsId);model.addAttribute(goods, goodsVoByGoodsId);// secKillStatus秒杀状态 0未开始 1进行中 2已结束// remainSeconds秒杀剩余时间 0未开始 0进行中 -1已结束// 获取该商品的秒杀开始时间和结束时间long startAt goodsVoByGoodsId.getStartDate().getTime();long endAt goodsVoByGoodsId.getEndDate().getTime();long now System.currentTimeMillis();// 根据当前时间与秒杀开始时间和结束时间的比较判断秒杀状态int secKillStatus 0;int remainSeconds 0;if (now startAt) {// 秒杀未开始secKillStatus 0;remainSeconds (int) ((startAt - now) / 1000);} else if (now endAt) {// 秒杀已结束secKillStatus 2;remainSeconds -1;} else {// 秒杀进行中secKillStatus 1;remainSeconds 0;}// 将秒杀状态和剩余时间存入model中返回到前端model.addAttribute(secKillStatus, secKillStatus);model.addAttribute(remainSeconds, remainSeconds);// 将用户信息存入model中返回到前端model.addAttribute(user, user);return goodsDetail;}2.前端
1.goodsDetail.html 图片下面添加一行秒杀开始时间 trtd秒杀开始时间/tdtd idstartTime th:text${#dates.format(goods.startDate,yyyy-MM-dd HH:mm:ss)}/tdtd idseckillTipinput typehidden idremainSecondsth:value${remainSeconds}/span th:if${secKillStatus eq 0}秒杀倒计时span idcountDownth:text${remainSeconds} /span秒/spanspan th:if${secKillStatus eq 1}秒杀进行中/spanspan th:if${secKillStatus eq 2}秒杀已结束/span/td/tr2.goodsDetail.html 添加计时器js代码
script$(function () {countDown();});function countDown() {var remainSeconds $(#remainSeconds).val();var timeout;
//秒杀还未开始if (remainSeconds 0) {timeout setTimeout(function () {$(#countDown).text(remainSeconds - 1);$(#remainSeconds).val(remainSeconds - 1);countDown();}, 1000);} else if (remainSeconds 0) {//秒杀进行中if (timeout) {//清空计时器clearTimeout(timeout);}$(#seckillTip).html(秒杀进行中);} else {$(#seckillTip).html(秒杀已结束);}}
/script3.测试
1.秒杀进行中 2.修改db的秒杀开始时间为明天 3.出现秒杀倒计时 4.修改db的秒杀结束时间比目前要早 5.秒杀已结束 2.秒杀按钮
1.前端
1.goodsDetail.html 添加抢购按钮 tdform idsecKillForm methodpost action/seckill/doSeckillinput typehidden idgoodsId namegoodsId th:value${goods.id}button classbtn btn-primary btn-block typesubmit idbuyButton 抢 购/button/form/td2.goodsDetail.html 根据秒杀状态控制按钮状态 2.测试
1.秒杀已结束按钮不可用 2.秒杀进行中按钮可用 3.秒杀未开始按钮不可用 3.秒杀基本功能不考虑高并发
1.数据库表设计
1.普通订单表
use seckill;
DROP TABLE IF EXISTS t_order;
CREATE TABLE t_order
(id BIGINT(20) NOT NULL AUTO_INCREMENT,user_id BIGINT(20) NOT NULL DEFAULT 0,goods_id BIGINT(20) NOT NULL DEFAULT 0,delivery_addr_id BIGINT(20) NOT NULL DEFAULT 0,goods_name VARCHAR(16) NOT NULL DEFAULT ,goods_count INT(11) NOT NULL DEFAULT 0,goods_price DECIMAL(10, 2) NOT NULL DEFAULT 0.00,order_channel TINYINT(4) NOT NULL DEFAULT 0 COMMENT 订单渠道 1pc2Android
3ios,status TINYINT(4) NOT NULL DEFAULT 0 COMMENT 订单状态0 新建未支付 1 已支付
2 已发货 3 已收货 4 已退款 5 已完成,create_date DATETIME DEFAULT NULL,pay_date DATETIME DEFAULT NULL,PRIMARY KEY (id)
) ENGINE INNODBAUTO_INCREMENT 600DEFAULT CHARSET utf8mb4;2.秒杀订单表
use seckill;
DROP TABLE IF EXISTS t_seckill_order;
CREATE TABLE t_seckill_order
(id BIGINT(20) NOT NULL AUTO_INCREMENT,user_id BIGINT(20) NOT NULL DEFAULT 0,order_id BIGINT(20) NOT NULL DEFAULT 0,goods_id BIGINT(20) NOT NULL DEFAULT 0,PRIMARY KEY (id),UNIQUE KEY seckill_uid_gid (user_id, goods_id) USING BTREE COMMENT 用户 id商品 id 的唯一索引解决同一个用户多次抢购
) ENGINE INNODBAUTO_INCREMENT 300DEFAULT CHARSET utf8mb4;2.MyBatis-Plus生成基础代码以t_order表为例
1.首先 ctrl shift c 复制基础包名一定要是带点的 2.右键表名选择 MybatisX-Generator 3.选择模块和基础包以及实体类名字 4.进行配置 5.点击生成检查代码
1.整个目录概览 2.把实体类移动到pojo并检查 3.检查 OrderMapper.java 发现没有加Mapper注解 4.查看启动类有MapperScan所以不用加Mapper了 5.检查OrderMapper.xml 6.检查application.yml是否自动扫描了Mapper.xml 7.检查OrderService.java 8.检查OrderServiceImpl.java 6.使用MyBatis-Plus生成基础代码的小结
启动类配置MapperScan注解扫描Mapper接口application.yml配置扫描Mapper.xml复制基础包名要带点的将Mapper.xml生成的最下面的删除即可
7.以同样的方式生成t_seckill_order
3.Service层
1.OrderService.java 新增秒杀方法返回订单
package com.sxs.seckill.service;import com.sxs.seckill.pojo.Order;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.vo.GoodsVo;/**
* author 8615941515990
* description 针对表【t_order】的数据库操作Service
* createDate 2024-05-08 16:05:29
*/
public interface OrderService extends IServiceOrder {/*** 方法秒杀* param user* param goodsVo* return*/Order seckill(User user, GoodsVo goodsVo);
}
2.OrderServiceImpl.java
package com.sxs.seckill.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxs.seckill.mapper.SeckillGoodsMapper;
import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillGoods;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.service.OrderService;
import com.sxs.seckill.mapper.OrderMapper;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.vo.GoodsVo;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** author 8615941515990* description 针对表【t_order】的数据库操作Service实现* createDate 2024-05-08 16:05:29*/
Service
public class OrderServiceImpl extends ServiceImplOrderMapper, Orderimplements OrderService {Resourceprivate SeckillGoodsMapper seckillGoodsMapper;Resourceprivate SeckillOrderService seckillOrderService;Overridepublic Order seckill(User user, GoodsVo goodsVo) {// 使用QueryWapper查询秒杀商品SeckillGoods seckillGoods seckillGoodsMapper.selectOne(new QueryWrapperSeckillGoods().eq(goods_id, goodsVo.getId()));// 将库存减一seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);// 更新秒杀商品库存seckillGoodsMapper.updateById(seckillGoods);// 创建订单Order order new Order();order.setUserId(user.getId());order.setGoodsId(goodsVo.getId());order.setDeliveryAddrId(0L);order.setGoodsName(goodsVo.getGoodsName());order.setGoodsCount(1);order.setGoodsPrice(goodsVo.getSeckillPrice());order.setOrderChannel(1);order.setStatus(0);order.setCreateDate(null);order.setPayDate(null);// 插入订单baseMapper.insert(order);// 生成秒杀商品订单seckillOrderService.insertSeckillOrder(order, goodsVo.getId());// 返回订单return order;}
}
3.SeckillOrderService.java 根据普通订单和商品id插入秒杀订单
package com.sxs.seckill.service;import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillOrder;
import com.baomidou.mybatisplus.extension.service.IService;/**
* author 8615941515990
* description 针对表【t_seckill_order】的数据库操作Service
* createDate 2024-05-08 16:20:14
*/
public interface SeckillOrderService extends IServiceSeckillOrder {/*** 根据普通订单和商品id插入秒杀订单*/void insertSeckillOrder(Order order, Long goodsId);
}
4.SeckillOrderServiceImpl.java
package com.sxs.seckill.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.SeckillOrder;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.mapper.SeckillOrderMapper;
import org.springframework.stereotype.Service;/**
* author 8615941515990
* description 针对表【t_seckill_order】的数据库操作Service实现
* createDate 2024-05-08 16:20:14
*/
Service
public class SeckillOrderServiceImpl extends ServiceImplSeckillOrderMapper, SeckillOrderimplements SeckillOrderService{Overridepublic void insertSeckillOrder(Order order, Long goodsId) {// 根据普通订单插入秒杀订单SeckillOrder seckillOrder new SeckillOrder();seckillOrder.setUserId(order.getUserId());seckillOrder.setOrderId(order.getId());seckillOrder.setGoodsId(goodsId);baseMapper.insert(seckillOrder);}
}
4.Controller层
1.SeckillController.java 完成基础版本的秒杀简单考虑库存和复购问题
package com.sxs.seckill.controller;import com.sxs.seckill.pojo.Order;
import com.sxs.seckill.pojo.User;
import com.sxs.seckill.service.GoodsService;
import com.sxs.seckill.service.OrderService;
import com.sxs.seckill.service.SeckillOrderService;
import com.sxs.seckill.vo.GoodsVo;
import com.sxs.seckill.vo.RespBeanEnum;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;/*** Description:** Author sun* Create 2024/5/8 18:49* Version 1.0*/
Controller
RequestMapping(/seckill)
public class SeckillController {Resourceprivate GoodsService goodsService;Resourceprivate OrderService orderService;Resourceprivate SeckillOrderService seckillOrderService;RequestMapping(/doSeckill)public String doSeckill(Model model, User user, Long goodsId) {// 判断用户是否登录if (user null) {return login;}// 将用户信息传递到页面model.addAttribute(user, user);// 根据goodsId获取GoodsVoGoodsVo goodsVoByGoodsId goodsService.findGoodsVoByGoodsId(goodsId);// 判断是否有库存if (goodsVoByGoodsId.getStockCount() 1) {// 没有库存返回秒杀失败页面model.addAttribute(errmsg, RespBeanEnum.EMPTY_STOCK.getMessage());return secKillFail;}// 通过秒杀订单表判断是否复购if (seckillOrderService.findSeckillOrderByUserIdAndGoodsId(user.getId(), goodsId) ! null) {// 重复购买返回秒杀失败页面model.addAttribute(errmsg, RespBeanEnum.REPEATE_ERROR.getMessage());return secKillFail;}// 秒杀Order seckill orderService.seckill(user, goodsVoByGoodsId);// 判断秒杀是否成功if (seckill null) {// 秒杀失败返回秒杀失败页面model.addAttribute(errmsg, RespBeanEnum.ERROR.getMessage());return secKillFail;}// 秒杀成功返回订单详情页面model.addAttribute(order, seckill);model.addAttribute(goods, goodsVoByGoodsId);// 返回订单详情页面return orderDetail;}
}
2.SeckillOrderService.java 新增方法根据用户id和商品id查找记录 /*** 根据用户id和商品id查询秒杀订单*/SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId);3.SeckillOrderServiceImpl.java Overridepublic SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId) {// 根据用户id和商品id查询秒杀订单return baseMapper.findSeckillOrderByUserIdAndGoodsId(userId, goodsId);}4.SeckillOrderMapper.java
package com.sxs.seckill.mapper;import com.sxs.seckill.pojo.SeckillOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;/**
* author 8615941515990
* description 针对表【t_seckill_order】的数据库操作Mapper
* createDate 2024-05-08 16:20:14
* Entity com.sxs.seckill.pojo.SeckillOrder
*/
public interface SeckillOrderMapper extends BaseMapperSeckillOrder {/*** 根据用户id和商品id查询秒杀订单*/SeckillOrder findSeckillOrderByUserIdAndGoodsId(Long userId, Long goodsId);
}
5.SeckillOrderMapper.xml
?xml version1.0 encodingUTF-8?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.sxs.seckill.mapper.SeckillOrderMapperresultMap idBaseResultMap typecom.sxs.seckill.pojo.SeckillOrderid propertyid columnid jdbcTypeBIGINT/result propertyuserId columnuser_id jdbcTypeBIGINT/result propertyorderId columnorder_id jdbcTypeBIGINT/result propertygoodsId columngoods_id jdbcTypeBIGINT//resultMapselect idfindSeckillOrderByUserIdAndGoodsId resultTypecom.sxs.seckill.pojo.SeckillOrderSELECT*FROMt_seckill_orderWHEREuser_id #{userId}ANDgoods_id #{goodsId}/select/mapper
5.前端
1.goodsDetail.html 修改点击抢购按钮的请求区分多环境 2.引入orderDetail.html
html langenxmlns:thhttp://www.thymeleaf.org
headtitle订单详情/titlemeta http-equivContent-Type contenttext/html; charsetUTF-8/!--jquery--script typetext/javascript th:src{/js/jquery.min.js}/script!-- bootstrap --link relstylesheet typetext/css th:href{/bootstrap/css/bootstrap.min.css}/script typetext/javascript th:src{/bootstrap/js/bootstrap.js}/script!-- layer --script typetext/javascript th:src{/layer/layer.js}/script!-- common.js --script typetext/javascript th:src{/js/common.js}/scriptstyle* {margin: 0;padding: 0;font-family: Open Sans, sans-serif;text-transform: uppercase;letter-spacing: 3px;font-size: 11px;}body {background: #c9302c;}.main-header {width: 100%;height: 100px;background: whitesmoke;display: block;}.navbar {display: inline-block;float: right;margin-right: 50px;margin-top: 30px;}.logo {display: inline-block;margin-top: 30px;margin-left: 30px;text-decoration: none;}.logo-lg {font-size: 20px;font-weight: lighter;color: #232324;}.logo-lg b {font-size: 20px;font-weight: lighter;color: #232324;}.container {background: #FFFFFF;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;width: 750px;}/style
/head
body
header idsite-header classmain-header!-- Logo --a classlogo onclicktoList()span classlogo-lgb商品抢购/b/span/anav classnavbar navbar-static-top!-- Sidebar toggle button--a href# classsidebar-toggle data-togglepush-menu rolebuttonspan classsr-onlyToggle navigation/spanspan classicon-bar/spanspan classicon-bar/spanspan classicon-bar/span/adiv classnavbar-custom-menuul classnav navbar-navli classdropdown user user-menua href# classdropdown-toggle data-toggledropdownimg classuser-image src/imgs/user.png height32 altUser
Imagespan classhidden-xs/span/aul classdropdown-menu!-- User image --li classuser-headerimg classimg-circle altUser ImagepHello ABC - Hello ABCsmallHello ABC/small/p/li!-- Menu Body --li classuser-body/lili classuser-footerdiv classpull-middlea onclicktoList() classbtn btn-lg btn-default btn-block退出系统/a/div/li/ul/li/ul/div/nav
/header
div classpanel panel-defaultdiv classpanel-heading stylebackground: #c9302c;color: white秒杀订单详情/divdiv classcontainertable classtable idordertrtd名称/tdtd idgoodName colspan3 th:text${goods.goodsName}/td/trtrtd图片/tdtd colspan2img idgoodImg width200 th:src{${goods.goodsImg}} height200//td/trtrtd订单价格/tdtd colspan2 idgoodPrice th:text${order.goodsPrice}/td/trtrtd下单时间/tdtd idcreateDate colspan2th:text${#dates.format(order.createDate,yyyy-MM-dd HH:mm:ss)}/td/trtrtd订单状态/tdtd idstatus span th:if${order.status eq 0}未支付/spanspan th:if${order.status eq 1}代发货/spanspan th:if${order.status eq 2}已发货/spanspan th:if${order.status eq 3}已收货/spanspan th:if${order.status eq 4}已退款/spanspan th:if${order.status eq 5}已完成/span/tdtdbutton classbtn btn-primary btn-block typesubmitidpayButton立即支付/button/td/trtrtd收货人/tdtd colspan2XXX 13300000000/td/trtrtd收货地址/tdtd colspan2北京市幸福小区 6 单元 101 号/td/tr/table/div
/div
script
/script
/body
/html3.引入secKillFail.html
html langen xmlns:thhttp://www.thymeleaf.org
headmeta charsetUTF-8titleTitle/titlestyle* {margin: 0;padding: 0;font-family: Open Sans, sans-serif;text-transform: uppercase;letter-spacing: 3px;font-size: 11px;}/style
/head
body
h1秒杀失败 /h1
p th:text${errmsg}/p
/body
/html6.测试
1.正常秒杀
1.初始秒杀商品表库存为10 2.秒杀1号商品 3.秒杀成功 4.秒杀商品库存减1 5.普通订单新增一条记录 6.秒杀订单新增一条记录 2.当前用户再次购买
成功跳转到限购页面 3.模拟库存不足的情况
1.将1号商品的库存修改为0 2.切换一个浏览器再次秒杀 3.成功跳转到库存不足的页面