2024年Java最全秒杀项目之秒杀商品操作,千峰Java

最后:学习总结——MyBtis知识脑图(纯手绘xmind文档)

学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。下方即为我手绘的MyBtis知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)

image

除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

,{field: ‘stockCount’, title: ‘秒杀库存’}

,{field: ‘startDate’, title: ‘活动开始时间’}

,{field: ‘endDate’, title: ‘活动结束时间’}

,{field: ‘goodsName’, title: ‘商品名称’}

]]

});

呈现界面:

二、秒杀商品添加

=========

1、后端:接收前端添加秒杀商品的数据


①、实体类vo:SeckillGoodsVo

private List<Map<String,Object>> goods;

修改实体类时间的类型:SeckillGoods

@ApiModelProperty(“秒杀开始时间”)

@TableField(“start_date”)

@DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”)

private Timestamp startDate;

@ApiModelProperty(“秒杀结束时间”)

@TableField(“end_date”)

@DateTimeFormat(pattern = “yyyy-MM-dd HH:mm:ss”)

private Timestamp endDate;

②、mapper层:SeckillGoodsMapper

int addGoods(SeckillGoodsVo seckillGoodsVo);

③、mapper.xml层:SeckillGoodsMapper

批量插入秒杀商品的sql语句:

insert into t_seckill_goods(goods_id, seckill_price, stock_count, start_date, end_date)

values

(#{g.gid},#{g.goodsPrice},#{g.goodsStock},#{startDate},#{endDate})

④、service层

ISeckillGoodsService:

ResponseResult<List> addGoods(SeckillGoodsVo seckillGoodsVo);

SeckillGoodsServiceImpl:

@Override

public ResponseResult<List> addGoods(SeckillGoodsVo seckillGoodsVo) {

int goods=seckillGoodsMapper.addGoods(seckillGoodsVo);

return ResponseResult.success(goods);

}

⑤、controller层

@RequestMapping(“/add”)

public ResponseResult<List> add(@RequestBody SeckillGoodsVo seckillGoodsVo){

return seckillGoodsService.addGoods(seckillGoodsVo);

}

2、前端


①、定义数据与刷新、添加

goodsList.js:

var layer,row,seckill_table

// 添加秒杀商品

$(“#seckill_add”).click(()=>{

layer.open({

type:2,

content: ‘/goods/SeckillGoodsOperate’,

area: [‘800px’,‘600px’]

})

})

// 秒杀商品刷新

var seckill_reload = ()=> {

seckill_table.reload({

page:{

curr:1 //current

}

});

}

var layer,row,seckill_table

layui.define(()=>{

let table=layui.table

layer=layui.layer

let $=layui.jquery

let normal_table=table.render({

elem: ‘#normal_goods’

,height: 500

,url: ‘/goods/queryAll’ //数据接口

,page: true //开启分页

,parseData(res){ //res 即为原始返回的数据

return {

“code”: res.code===200?0:1, //解析接口状态

“msg”: res.message, //解析提示文本

“count”: res.total, //解析数据长度

“data”: res.data //解析数据列表

};

},

//用于对分页请求的参数:page、limit重新设定名称

request: {

pageName: ‘page’ //页码的参数名称,默认:page

,limitName: ‘rows’ //每页数据量的参数名,默认:limit

}

,cols: [[ //表头

{field: ‘gid’, title: ‘商品编号’, width:80, sort: true, fixed: ‘left’}

,{field: ‘goodsName’, title: ‘商品名字’}

,{field: ‘goodsTitle’, title: ‘商品标题’}

,{field: ‘goodsImg’,

title: ‘商品图片’,

width:200,

templet: (goods) => <b onmouseover='showImg("${goods.goodsImg}",this)'> + goods.goodsImg + </b> }

,{field: ‘goodsDetail’, title: ‘商品详情’}

,{field: ‘goodsPrice’, title: ‘商品价格’, sort: true}

,{field: ‘goodsStock’, title: ‘商品库存’, sort: true}

,{field: ‘operate’, title: ‘商品操作’,toolbar: ‘#button_1’}

]]

});

// 刷新表格

let reloadTable=()=>{

let goodsName=$(“#normal_value”).val()

// 【JS】自动化渲染的重载,重载表格

normal_table.reload({

where: {

//设定异步数据接口的额外参数,height: 300

goodsName

},

page:{

curr:1 //current

}

});

}

// 搜索

$(“#normal_search”).click(reloadTable)

// 增加

$(“#normal_add”).click(()=>{

row = null

openDialog()

})

//工具条事件

table.on(‘tool(normal_goods)’, function(obj) { //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter=“对应的值”

let data = obj.data; //获得当前行数据

let layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)

let tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)

if (layEvent === ‘normal_del’) { //删除

row = data//获得当前行的数据

let url=“/goods/del/”+data.gid

layer.confirm(‘确定删除吗?’,{title:‘删除’}, function(index){

//向服务端发送删除指令og

$.getJSON(url,{gid:data.gid}, function(ret){

layer.close(index);//关闭弹窗

reloadTable()

});

layer.close(index);//关闭弹窗

});

}

if (layEvent === ‘normal_edit’) { //编辑

row = data

openDialog()

}

})

// 页面弹出

let openDialog=()=>{

// 如果是iframe层

layer.open({

type: 2,

content: ‘/goods/goodsOperate’, //这里content是一个URL,如果你不想让iframe出现滚动条,你还可以content: [‘http://sentsin.com’, ‘no’]

area:[‘800px’,‘600px’],

btn: [‘确定’,‘取消’],

yes(index,layero){

let url=“/goods/insert”

// 拿到表格数据

let data=$(layero).find(“iframe”)[0].contentWindow.getFormData()

if(row) {

url=“/goods/edit”

}

$.ajax({

url,

data,

datatype: “json”,

success(res){

layer.closeAll()

reloadTable()

layer.msg(res.message)

}

})

}

});

}

// -------------------------秒杀商品-------------------------------------------

seckill_table=table.render({

elem: ‘#seckill_goods’

,height: 500

,url: ‘/seckillGoods/queryAll’ //数据接口

,parseData(res){ //res 即为原始返回的数据

return {

“code”: res.code===200?0:1, //解析接口状态

“msg”: res.message, //解析提示文本

“count”: res.total, //解析数据长度

“data”: res.data //解析数据列表

};

},

cols: [[ //表头

{field: ‘id’, title: ‘秒杀商品编号’, width:80, sort: true}

,{field: ‘goodsId’, title: ‘商品名字id’}

,{field: ‘seckillPrice’, title: ‘秒杀价格’}

,{field: ‘stockCount’, title: ‘秒杀库存’}

,{field: ‘startDate’, title: ‘活动开始时间’}

,{field: ‘endDate’, title: ‘活动结束时间’}

,{field: ‘goodsName’, title: ‘商品名称’}

]]

});

// 添加秒杀商品

$(“#seckill_add”).click(()=>{

layer.open({

type:2,

content: ‘/goods/SeckillGoodsOperate’,

area: [‘800px’,‘600px’]

})

})

})

// 图片显示

let showImg = (src,obj)=> {

layer.tips(<img src="${src}" width="100px">, obj);

}

// 秒杀商品刷新

var seckill_reload = ()=> {

seckill_table.reload({

page:{

curr:1 //current

}

});

}

②、增加秒杀商品弹出页面样式

保 存

③、实现增加秒杀商品

seckillGoodsOperate.js:

layui.define(()=>{

let table=layui.table

let laydate = layui.laydate

let $=layui.jquery

let layer=layui.layer

// 读取普通商品

table.render({

elem: ‘#tb_goods’

,height: 500

,url: ‘/goods/queryAll’ //数据接口

,page: true //开启分页

,parseData(res){ //res 即为原始返回的数据

return {

“code”: res.code===200?0:1, //解析接口状态

“msg”: res.message, //解析提示文本

“count”: res.total, //解析数据长度

“data”: res.data //解析数据列表

};

},

//用于对分页请求的参数:page、limit重新设定名称

request: {

pageName: ‘page’ //页码的参数名称,默认:page

,limitName: ‘rows’ //每页数据量的参数名,默认:limit

}

,cols: [[ //表头

// 全选按钮

{field: ‘’, type:“checkbox”}

,{field: ‘gid’, title: ‘商品编号’, width:80}

,{field: ‘goodsName’, title: ‘商品名字’}

,{field: ‘goodsTitle’, title: ‘商品标题’}

,{field: ‘goodsDetail’, title: ‘商品详情’}

,{field: ‘goodsPrice’, title: ‘商品价格’, sort: true}

,{field: ‘goodsStock’, title: ‘商品库存’, sort: true}

]]

});

// 构建时间选择器

//执行一个laydate实例

laydate.render({

elem: ‘#dt’, //指定元素

type: “datetime”,

range: “~”

});

$(“#btn_save”).click(()=>{

// 获取时间

let val=$(“#dt”).val()

if(!val){

layer.msg(“请选择时间”)

return

}

// 解析时间2022-2-2 ~2022-5-2

let startDate=new Date(val.split(“~”)[0]).getTime()

let endDate=new Date(val.split(“~”)[1]).getTime()

// 获得选中的普通商品,获取选中行的数据

let rows= table.checkStatus(‘tb_goods’).data; //idTest 即为基础参数 id 对应的值

if(!rows||rows.length===0){

layer.msg(“请选择数据”)

return

}

layer.prompt(function(value, index, elem){

// 修改每个商品的数量

rows.forEach(e=>{

e.goodsStock=value

})

let data={

startDate,

endDate,

goods:rows

}

// 访问后台的秒杀商品的接口

$.ajax({

url: “/seckillGoods/add”,

contentType:‘application/json’,

data: JSON.stringify(data),

datatype:“json”,//返回类型

type:“post”,

success(res){

parent.seckill_reload()

layer.closeAll()

parent.layer.closeAll()

layer.msg(res.message)

}

})

});

})

})

④、展示结果

 增加成功:

三、秒杀商品的操作

==========

1、后端操作秒杀单个商品详情


①、mapper层

SeckillGoodsMapper:

Map<String,Object> querySeckillGoodsById(Long id);

mapper.xml文件:SeckillGoodsMapper.xml

select sg.id,

sg.goods_id,

sg.seckill_price,

sg.stock_count,

sg.start_date,

sg.end_date,

g.goods_img,

g.goods_title,

g.goods_detail,

g.goods_name,

(

case

when current_timestamp < sg.start_date then 0

when (current_timestamp between sg.start_date and sg.end_date) then 1

when current_timestamp > sg.end_date then 2

end

) goods_status

from t_goods g,

t_seckill_goods sg

where g.gid = sg.goods_id

and sg.id = #{0}

②、service层

ISeckillGoodsService:

Map<String,Object> querySeckillGoodsById(Long id);

SeckillGoodsServiceImpl:

@Override

public Map<String, Object> querySeckillGoodsById(Long id) {

return seckillGoodsMapper.querySeckillGoodsById(id);

}

③、controller层:SeckillGoodsController

package com.example.seckill.controller;

import com.example.seckill.service.ISeckillGoodsService;

import com.example.seckill.util.response.ResponseResult;

import com.example.seckill.vo.SeckillGoodsVo;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.*;

import org.springframework.web.servlet.ModelAndView;

import java.util.List;

/**

  • 秒杀商品信息表 前端控制器

  • @author lv

  • @since 2022-03-19

*/

@Controller

@RequestMapping(“/seckillGoods”)

public class SeckillGoodsController {

@Autowired

private ISeckillGoodsService seckillGoodsService;

// 返回json

@ResponseBody

@RequestMapping(“/queryAll”)

public ResponseResult<List> queryAll(){

return seckillGoodsService.queryAll();

}

@ResponseBody

@RequestMapping(“/add”)

public ResponseResult<List> add(@RequestBody SeckillGoodsVo seckillGoodsVo){

return seckillGoodsService.addGoods(seckillGoodsVo);

}

// 正常跳转界面

@RequestMapping(“/query/{id}”)

public ModelAndView querySeckillGoodsById(@PathVariable(“id”) Long id) {

ModelAndView mv = new ModelAndView(“/goods/goodsSeckill”);

mv.addObject(“goods”, seckillGoodsService.querySeckillGoodsById(id));

return mv;

}

}

2、前端展示


①、在goodsList.js增加列的操作

{

field: ‘’, title: ‘操作’, width: 140,

templet: function (d) {

return `

删除

秒杀

`;

}

}

②、添加秒杀详情界面 :goodsSkill.ftl

<#include “…/common/head.ftl”/>

商品图片 商品名称

${goods[‘goods_name’]}

商品标题

${goods[‘goods_title’]}

商品价格

${goods[‘seckill_price’]}

开始时间

${goods[‘start_date’]?string(“yyyy-MM-dd HH:mm:ss”)}

${goods[‘end_date’]?string(“yyyy-MM-dd HH:mm:ss”)}

<#if goods[‘goods_status’]==0>

活动未开始

<#elseif goods[‘goods_status’]==1>

活动热卖中

立即抢购

<#else>

活动已结束

</#if>

③、实现:goodsSkill.js

let layer, form, $;

layui.define(() => {

layer = layui.layer

form = layui.form

$ = layui.jquery

$(‘#buy’).click(() => {

$.ajax({

url: ‘/seckillOrder/addOrder’,

data: {goodsId: $(‘#goodsId’).val()},

dataType: ‘json’,

type: ‘post’,

async: false,

success: function (rs) {

if (rs.code === 200)

layer.msg(rs.message)

else

layer.msg(rs.message)

}

})

});

})

④、展示效果

点击秒杀:

3、后端操作秒杀抢购功能


①、导入雪花id工具包:SnowFlake

package com.example.seckill.util;

@SuppressWarnings(“all”)

public class SnowFlake {

/**

  • 起始的时间戳

*/

private final static long START_STMP = 1480166465631L;

/**

  • 每一部分占用的位数

*/

private final static long SEQUENCE_BIT = 12; //序列号占用的位数

private final static long MACHINE_BIT = 5; //机器标识占用的位数

private final static long DATACENTER_BIT = 5;//数据中心占用的位数

/**

  • 每一部分的最大值

*/

private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);

private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);

private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);

/**

  • 每一部分向左的位移

*/

private final static long MACHINE_LEFT = SEQUENCE_BIT;

private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;

private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;

private long datacenterId; //数据中心

private long machineId; //机器标识

private long sequence = 0L; //序列号

private long lastStmp = -1L;//上一次时间戳

public SnowFlake(long datacenterId, long machineId) {

if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {

throw new IllegalArgumentException(“datacenterId can’t be greater than MAX_DATACENTER_NUM or less than 0”);

}

if (machineId > MAX_MACHINE_NUM || machineId < 0) {

throw new IllegalArgumentException(“machineId can’t be greater than MAX_MACHINE_NUM or less than 0”);

}

this.datacenterId = datacenterId;

this.machineId = machineId;

}

public static void main(String[] args) {

SnowFlake snowFlake = new SnowFlake(2, 3);

long start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

System.out.println(snowFlake.nextId());

}

System.out.println(System.currentTimeMillis() - start);

}

/**

  • 产生下一个ID

  • @return

最后

由于文案过于长,在此就不一一介绍了,这份Java后端架构进阶笔记内容包括:Java集合,JVM、Java并发、微服务、SpringNetty与 RPC 、网络、日志 、Zookeeper 、Kafka 、RabbitMQ 、Hbase 、MongoDB、Cassandra 、Java基础、负载均衡、数据库、一致性算法、Java算法、数据结构、分布式缓存等等知识详解。

image

本知识体系适合于所有Java程序员学习,关于以上目录中的知识点都有详细的讲解及介绍,掌握该知识点的所有内容对你会有一个质的提升,其中也总结了很多面试过程中遇到的题目以及有对应的视频解析总结。

image

image

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

e = 0L; //序列号

private long lastStmp = -1L;//上一次时间戳

public SnowFlake(long datacenterId, long machineId) {

if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {

throw new IllegalArgumentException(“datacenterId can’t be greater than MAX_DATACENTER_NUM or less than 0”);

}

if (machineId > MAX_MACHINE_NUM || machineId < 0) {

throw new IllegalArgumentException(“machineId can’t be greater than MAX_MACHINE_NUM or less than 0”);

}

this.datacenterId = datacenterId;

this.machineId = machineId;

}

public static void main(String[] args) {

SnowFlake snowFlake = new SnowFlake(2, 3);

long start = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

System.out.println(snowFlake.nextId());

}

System.out.println(System.currentTimeMillis() - start);

}

/**

  • 产生下一个ID

  • @return

最后

由于文案过于长,在此就不一一介绍了,这份Java后端架构进阶笔记内容包括:Java集合,JVM、Java并发、微服务、SpringNetty与 RPC 、网络、日志 、Zookeeper 、Kafka 、RabbitMQ 、Hbase 、MongoDB、Cassandra 、Java基础、负载均衡、数据库、一致性算法、Java算法、数据结构、分布式缓存等等知识详解。

[外链图片转存中…(img-Bw7G9pm3-1714894863474)]

本知识体系适合于所有Java程序员学习,关于以上目录中的知识点都有详细的讲解及介绍,掌握该知识点的所有内容对你会有一个质的提升,其中也总结了很多面试过程中遇到的题目以及有对应的视频解析总结。

[外链图片转存中…(img-943I1QMM-1714894863475)]

[外链图片转存中…(img-epGycb5b-1714894863475)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java实现秒杀系统@Controller @RequestMapping("seckill")//url:/模块/资源/{id}/细分 /seckill/list public class SeckillController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private SeckillService seckillService; @RequestMapping(value="/list",method = RequestMethod.GET) public String list(Model model){ //获取列表页 List list=seckillService.getSeckillList(); model.addAttribute("list",list); //list.jsp+model = ModelAndView return "list";//WEB-INF/jsp/"list".jsp } @RequestMapping(value = "/{seckillId}/detail",method = RequestMethod.GET) public String detail(@PathVariable("seckillId") Long seckillId, Model model){ if (seckillId == null){ return "redirect:/seckill/list"; } Seckill seckill = seckillService.getById(seckillId); if (seckill == null){ return "forward:/seckill/list"; } model.addAttribute("seckill",seckill); return "detail"; } //ajax json @RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) @ResponseBody public SeckillResult exposer(@PathVariable("seckillId") Long seckillId){ SeckillResult result; try { Exposer exposer =seckillService.exportSeckillUrl(seckillId); result = new SeckillResult(true,exposer); } catch (Exception e) { logger.error(e.getMessage(),e); result = new SeckillResult(false,e.getMessage()); } return result; } @RequestMapping(value = "/{seckillId}/{md5}/execution", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"} ) @ResponseBody public SeckillResult execute(@PathVariable("seckillId")Long seckillId,

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值