发布时间:2025-12-10 11:35:11 浏览次数:4
1、去后台管理系统添加新的秒杀场次(注意这里不能把之前的秒杀场次给修改后再次使用,还有时间必须要三天内)
2、在秒杀服务中的定时任务修改一下每5s上架一次(这样是为了更快上架)
然后就可以看到上架的秒杀商品了
通过设置订时任务来自动上架最近三天需要秒杀的商品信息到redis缓存实现秒杀服务预热效果
1、首先设置定时器类来定时自动上架最近三天需要秒杀的商品信息到redis缓存
采用了分布式锁来保证幂等性(其实就是加个分布式锁来确保多个秒杀服务同时在线时只有一个服务成功上架秒杀商品)
分布式系统中的幂等性概念:用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
幂等场景
2、在SeckillServiceImpl实现uploadSeckillSkuLatest3Days方法
实现uploadSeckillSkuLatest3Days方法的代码
@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate CouponFeignService couponFeignService;@Autowiredprivate ProductFeignService productFeignService;@Autowiredprivate RedissonClient redissonClient;@Autowiredprivate RabbitTemplate rabbitTemplate;private final String SESSION__CACHE_PREFIX = "seckill:sessions:";private final String SECKILL_CHARE_PREFIX = "seckill:skus";private final String SKU_STOCK_SEMAPHORE = "seckill:stock:"; //+商品随机码/*** 上架三天需要秒杀的商品到缓存里*/@Overridepublic void uploadSeckillSkuLatest3Days() {//1、扫描最近三天的商品需要参加秒杀的活动R lates3DaySession = couponFeignService.getLates3DaySession();if (lates3DaySession.getCode() == 0) {//获取远程调用查询到的秒杀活动List<SeckillSessionWithSkusVo> sessionData = lates3DaySession.getData("data", new TypeReference<List<SeckillSessionWithSkusVo>>() {});//缓存到Redis//1、封装秒杀活动信息saveSessionInfos(sessionData);//2、封装秒杀活动的关联商品信息saveSessionSkuInfo(sessionData);}}/*** 封装秒杀活动信息到缓存里* @param sessions 秒杀活动信息*/private void saveSessionInfos(List<SeckillSessionWithSkusVo> sessions) {if (sessions!=null){sessions.stream().forEach(session -> {//获取当前活动的开始和结束时间的时间戳long startTime = session.getStartTime().getTime();long endTime = session.getEndTime().getTime();//存入到Redis中的key格式例如seckill:sessions:1648099200000_1648123200000//seckill:sessions:是前缀,1648099200000表示秒杀活动开始的时间,1648123200000表示秒杀活动结束的时间String key = SESSION__CACHE_PREFIX + startTime + "_" + endTime;//判断Redis中是否有该信息,如果没有才进行添加Boolean hasKey = redisTemplate.hasKey(key);//缓存活动信息if (!hasKey) {//获取到活动中所有商品的skuId 格式例如:4-47List<String> skuIds = session.getRelationSkus().stream().map(item -> item.getPromotionSessionId() + "-" + item.getSkuId().toString()).collect(Collectors.toList());//leftPushAll是批量存入缓存/**格式是每一个缓存中秒杀活动的格式是key:seckill:sessions:1648099200000_1648123200000,value:4-47**/redisTemplate.opsForList().leftPushAll(key,skuIds);}});}else {log.error("没有秒杀活动");}}/*** 封装秒杀活动的关联商品信息到缓存里* @param sessions 秒杀活动信息*/private void saveSessionSkuInfo(List<SeckillSessionWithSkusVo> sessions) {if (sessions!=null){sessions.stream().forEach(session -> {//准备hash操作,绑定hash值seckill:skusBoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(SECKILL_CHARE_PREFIX);//遍历秒杀活动中的商品项(seckillSkuVo表示的就是每个遍历的商品项)session.getRelationSkus().stream().forEach(seckillSkuVo -> {//生成随机码String token = UUID.randomUUID().toString().replace("-", "");//查看redis中有没有这个key (秒杀场次id_秒杀商品id)String redisKey = seckillSkuVo.getPromotionSessionId().toString() + "-" + seckillSkuVo.getSkuId().toString();if (!operations.hasKey(redisKey)) {//缓存我们商品信息(SeckillSkuRedisTo是存入缓存中的对象)SeckillSkuRedisTo redisTo = new SeckillSkuRedisTo();Long skuId = seckillSkuVo.getSkuId();//1、先查询sku的基本信息,调用远程服务R info = productFeignService.getSkuInfo(skuId);if (info.getCode() == 0) {SkuInfoVo skuInfo = info.getData( "skuInfo",new TypeReference<SkuInfoVo>(){});redisTo.setSkuInfo(skuInfo);}//2、sku的秒杀信息BeanUtils.copyProperties(seckillSkuVo,redisTo);//3、设置当前商品的秒杀时间信息redisTo.setStartTime(session.getStartTime().getTime());redisTo.setEndTime(session.getEndTime().getTime());//4、设置商品的随机码(防止恶意攻击)redisTo.setRandomCode(token);//序列化json格式存入Redis中String seckillValue = JSON.toJSONString(redisTo);//秒杀活动的商品项的详细信息存入redis/**格式是key:4_47 value:SeckillSkuRedisTo对象的String类型**/operations.put(seckillSkuVo.getPromotionSessionId().toString() + "-" + seckillSkuVo.getSkuId().toString(),seckillValue);//如果当前这个场次的商品库存信息已经上架就不需要上架/**5、使用库存作为分布式Redisson信号量(限流)**///把每个秒杀商品的总数量作为信号量存入redis缓存,信号量标识seckill:stock:+随机(相当于key)RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMAPHORE + token);/**库存的格式key:seckill:stock:5d1df46618d34f9f9808f25cda60ba01 value:秒杀商品的总数量 其中5d1df46618d34f9f9808f25cda60ba01是随机码**/semaphore.trySetPermits(seckillSkuVo.getSeckillCount());}});});}else {log.error("没有秒杀活动");}}实现uploadSeckillSkuLatest3Days方法的总流程:
第一步的实现细节
远程调用Coupon服务的SeckillSessionController控制器代码块
/*** 查询最近三天需要参加秒杀商品的信息* @return*/@GetMapping(value = "/Lates3DaySession")public R getLates3DaySession() {List<SeckillSessionEntity> seckillSessionEntities = seckillSessionService.getLates3DaySession();return R.ok().setData(seckillSessionEntities);}远程调用Coupon服务的SeckillSessionController控制器getLates3DaySession方法代码块
分流程:
Redis缓存中秒杀活动的格式如下:
通过HashMap结构把每个秒杀商品的详细信息以下面的格式存到Redis中,Redis缓存中具体格式如下:
Redission实现分布式信号量设置时就会把信号量以key-value的格式存到reids缓存中,Redis缓存中信号量格式如下:
saveSessionSkuInfo方法具体流程如下:
1、商城首页每次刷新都发这个请求来获取当前的所有秒杀商品信息
// 秒杀服务请求$.get("http://seckill.saodaimall.com/getCurrentSeckillSkus", function (res) {if (res.data.length > 0) {res.data.forEach(function (item) {$("<li onclick='toDetail(" + item.skuId + ")'></li>").append($("<img style='width: 130px; height: 130px' src='" + item.skuInfo.skuDefaultImg + "' />")).append($("<p>"+item.skuInfo.skuTitle+"</p>")).append($("<span>" + item.seckillPrice + "</span>")).append($("<s>" + item.skuInfo.price + "</s>")).appendTo("#seckillSkuContent");})}})2、编写秒杀服务的SeckillController控制器来处理上面的请求/getCurrentSeckillSkus
@Autowiredprivate SeckillService seckillService;/*** 当前时间可以参与秒杀的商品信息* @return*/@GetMapping(value = "/getCurrentSeckillSkus")@ResponseBodypublic R getCurrentSeckillSkus() {//获取到当前可以参加秒杀商品的信息List<SeckillSkuRedisTo> vos = seckillService.getCurrentSeckillSkus();return R.ok().setData(vos);}/*** 获取到当前可以参加秒杀商品的信息* @return*/@Overridepublic List<SeckillSkuRedisTo> getCurrentSeckillSkus() {//1、确定当前属于哪个秒杀场次//获取当前时间long currentTime = System.currentTimeMillis();//查找所有redis里的秒杀活动的信息,从Redis中查询到所有key以seckill:sessions开头的所有数据(其实就是查找所有redis里的秒杀活动的信息)Set<String> keys = redisTemplate.keys(SESSION__CACHE_PREFIX + "*");for (String key : keys) {// redis中秒杀活动取出来的格式是seckill:sessions:1594396764000_1594453242000//把seckill:sessions:前缀给去掉String replace = key.replace(SESSION__CACHE_PREFIX, "");String[] s = replace.split("_");//获取存入Redis商品的开始时间long startTime = Long.parseLong(s[0]);//获取存入Redis商品的结束时间long endTime = Long.parseLong(s[1]);//判断是否是当前秒杀场次 seckill:sessions:1648099200000_1648123200000if (currentTime >= startTime && currentTime <= endTime) {//2、获取这个秒杀场次需要的所有商品信息也就是key对应的value(这个key是当前秒杀活动的key)-100到100表示取出所有的keyList<String> range = redisTemplate.opsForList().range(key, -100, 100);//SECKILL_CHARE_PREFIX是seckill:skusBoundHashOperations<String, String, String> hasOps = redisTemplate.boundHashOps(SECKILL_CHARE_PREFIX);//3、multiGet是多个key对应的value值(获取所有的秒杀商品的详细信息)List<String> listValue = hasOps.multiGet(range);if (listValue != null && listValue.size() >= 0) {List<SeckillSkuRedisTo> collect = listValue.stream().map(item -> {SeckillSkuRedisTo redisTo = JSON.parseObject(items, SeckillSkuRedisTo.class);// redisTo.setRandomCode(null);当前秒杀开始需要随机码return redisTo;}).collect(Collectors.toList());return collect;}break;}}return null;}首先拿到所有秒杀活动信息的key值keys,然后判断秒杀活动的开始和结束时间是否在当前时间内,也就是选中当前时间参加秒杀的秒杀活动,存到Redis缓存中秒杀活动的格式如下:
通过遍历所有的key,判断每个key的时间戳来选中当前时间参加秒杀的秒杀活动,然后拿出所有参加的秒杀活动里的所有秒杀商品信息range,通过HashMap结构把每个秒杀商品的详细信息以下面的格式存到Redis中,Redis缓存中具体格式如下:
这里可以看出上面秒杀活动的值是作为下面秒杀商品的key值的,通过这个来把秒杀活动和秒杀商品关联起来,可以获取所有的秒杀商品的详细信息,最后把json字符串转为SeckillSkuRedisTo对象(秒杀商品的详细信息)封装成一个集合List<SeckillSkuRedisTo>
分流程:
//新增的秒杀属性(用于判断该商品项有没有参加秒杀活动)
private SeckillSkuVo seckillSkuVo;package com.saodai.saodaimall.product.vo;import com.saodai.saodaimall.product.entity.SkuImagesEntity;import com.saodai.saodaimall.product.entity.SkuInfoEntity;import com.saodai.saodaimall.product.entity.SpuInfoDescEntity;import lombok.Data;import lombok.ToString;import java.util.List;/*** sku详细信息**/@ToString@Datapublic class SkuItemVo {//1、sku基本信息的获取 pms_sku_infoprivate SkuInfoEntity info;private boolean hasStock = true;//2、sku的图片信息 pms_sku_imagesprivate List<SkuImagesEntity> images;//3、获取spu的销售属性组合private List<SkuItemSaleAttrVo> saleAttr;//4、获取spu的介绍private SpuInfoDescEntity desc;//5、获取spu的规格参数信息private List<SpuItemAttrGroupVo> groupAttrs;//6、秒杀商品信息private SeckillSkuVo seckillSkuVo;} package com.saodai.saodaimall.product.vo;import lombok.Data;import java.math.BigDecimal;/*** 秒杀商品的信息**/@Datapublic class SeckillSkuVo {/*** 活动id*/private Long promotionId;/*** 活动场次id*/private Long promotionSessionId;/*** 商品id*/private Long skuId;/*** 秒杀价格*/private BigDecimal seckillPrice;/*** 秒杀总量*/private Integer seckillCount;/*** 每人限购数量*/private Integer seckillLimit;/*** 排序*/private Integer seckillSort;//当前商品秒杀的开始时间private Long startTime;//当前商品秒杀的结束时间private Long endTime;//当前商品秒杀的随机码private String randomCode;}流程
1、远程调用秒杀服务查看当前商品有没有从参加秒杀活动
2、如果超过了秒杀活动的最后期限就设置秒杀信息为空
3、把远程查询到的该商品的秒杀信息封装在SkuItemVo对象中
//秒杀CompletableFuture<Void> seckillFuture = CompletableFuture.runAsync(() -> {//3、远程调用查询当前sku是否参与秒杀优惠活动R skuSeckilInfo = seckillFeignService.getSkuSeckilInfo(skuId);if (skuSeckilInfo.getCode() == 0) {//查询成功SeckillSkuVo seckilInfoData = skuSeckilInfo.getData("data", new TypeReference<SeckillSkuVo>() {});//如果超过了秒杀活动的最后期限就设置秒杀信息为空if (seckilInfoData != null) {long currentTime = System.currentTimeMillis();if (currentTime > seckilInfoData.getEndTime()) {skuItemVo.setSeckillSkuVo(null);}}skuItemVo.setSeckillSkuVo(seckilInfoData);}}, executor);//等到所有任务都完成CompletableFuture.allOf(saleAttrFuture,descFuture,baseAttrFuture,imageFuture,seckillFuture).get();流程:
1、绑定HashMap操作,Hash值为seckill:skus
2、获取所有的key,key的格式为4-47
3、遍历所有的key并且用正则表达式来判断这个商品有没有对应的key
4、如果这个商品参加了秒杀就取出reids中的数据并且转为SeckillSkuRedisTo对象
5、如果当前时间大于等于秒杀活动开始时间并且要小于活动结束时间
动态拼装秒杀商品信息
发送http://seckill.saodaimall.com/getCurrentSeckillSkus这个get请求后由秒杀服务的SeckillController的getCurrentSeckillSkus方法来处理,处理后返回List<SeckillSkuRedisTo>集合,也就是res代指的是后端封装好的List<SeckillSkuRedisTo>集合
// 秒杀服务请求$.get("http://seckill.saodaimall.com/getCurrentSeckillSkus", function (res) {if (res.data.length > 0) {res.data.forEach(function (item) {//给每一个秒杀商品项绑定一个点击事件toDetail $("<li onclick='toDetail(" + item.skuId + ")'></li>").append($("<img style='width: 130px; height: 130px' src='" + item.skuInfo.skuDefaultImg + "' />")).append($("<p>"+item.skuInfo.skuTitle+"</p>")).append($("<span>" + item.seckillPrice + "</span>")).append($("<s>" + item.skuInfo.price + "</s>")).appendTo("#seckillSkuContent");})}})//点击秒杀商品后跳到商品详细界面function toDetail(skuId) {location.href = "http://item.saodaimall.com/" + skuId + ".html";}上面动态拼装秒杀商品信息就是按下面的模板拼装的,只是说用的dom动态拼装,而下面的是静态的
<p class="swiper-slide"><ul><li><img src=" /static/index/img/section_second_list_img6.jpg" alt=""><p>Apple iMac 21.5英寸一体机(2017新款四核Core i5 处理器/8GB内存/1TB/RP555显卡/4K屏 MNDY2CH/A) Apple iMac 21.5英寸一体机(2017新款四核Core i5 处理</p><span>¥9588.00</span><s>¥10288.00</s></li></ul></p>下面的item是商品服务web里的ItemController控制器返回的SkuItemVo对象(其实就是商品项详细页面发送的请求来获取商品详细信息的,seckillSkuVo是SkuItemVo对象里的秒杀商品信息)
package com.saodai.saodaimall.product.vo;import com.saodai.saodaimall.product.entity.SkuImagesEntity;import com.saodai.saodaimall.product.entity.SkuInfoEntity;import com.saodai.saodaimall.product.entity.SpuInfoDescEntity;import lombok.Data;import lombok.ToString;import java.util.List;/*** sku详细信息**/@ToString@Datapublic class SkuItemVo {//1、sku基本信息的获取 pms_sku_infoprivate SkuInfoEntity info;private boolean hasStock = true;//2、sku的图片信息 pms_sku_imagesprivate List<SkuImagesEntity> images;//3、获取spu的销售属性组合private List<SkuItemSaleAttrVo> saleAttr;//4、获取spu的介绍private SpuInfoDescEntity desc;//5、获取spu的规格参数信息private List<SpuItemAttrGroupVo> groupAttrs;//6、秒杀商品的优惠信息private SeckillSkuVo seckillSkuVo;}代码讲解
1、${#dates.createNow().getTime() < item.seckillSkuVo.startTime}
#dates表示日期工具类,.createNow().getTime() < item.seckillSkuVo.startTime表示获取当前时间然后比秒杀开始时间要早就提示哪个时候开始秒杀
2、[[${#dates.format(new java.util.Date(item.seckillSkuVo.startTime),"yyyy-MM-dd HH:mm:ss")}]]
表示获取秒杀活动开始的时间并进行日期格式化,格式化的样式yyyy-MM-dd HH:mm:ss
3、${#dates.createNow().getTime() >= item.seckillSkuVo.startTime && #dates.createNow().getTime() <= item.seckillSkuVo.endTime}
如果当前商品的当前时间在秒杀活动的时间范围内就显示秒杀价
4、[[${#numbers.formatDecimal(item.seckillSkuVo.seckillPrice,1,2)}]]
对秒杀价进行格式化,1表示小数点左边为1位数,2表示小数点右边为两位数,例如9.99
<li style="color: red" th:if="${item.seckillSkuVo != null}"><span th:if="${#dates.createNow().getTime() < item.seckillSkuVo.startTime}">商品将会在[[${#dates.format(new java.util.Date(item.seckillSkuVo.startTime),"yyyy-MM-dd HH:mm:ss")}]]进行秒杀</span><span th:if="${#dates.createNow().getTime() >= item.seckillSkuVo.startTime && #dates.createNow().getTime() <= item.seckillSkuVo.endTime}">秒杀价 [[${#numbers.formatDecimal(item.seckillSkuVo.seckillPrice,1,2)}]]</span></li>代码讲解
th:attr="skuId=${item.info.skuId},sessionId=${item.seckillSkuVo.promotionSessionId},code=${item.seckillSkuVo.randomCode}
自定义属性名skuId(商品项的id)、sessionId(秒杀活动场次的id)、code(随机码,用于防止恶意抢单),自定义这三个属性是因为后面实现立即请购商品时需要用(也就是第四步)
<p class="box-btns-two"th:if="${item.seckillSkuVo == null }"><a class="addToCart" href="http://cart.saodaimall.com/addToCart" th:attr="skuId=${item.info.skuId}">加入购物车</a></p><p class="box-btns-two"th:if="${item.seckillSkuVo != null && (#dates.createNow().getTime() >= item.seckillSkuVo.startTime && #dates.createNow().getTime() <= item.seckillSkuVo.endTime)}"><a class="seckill" href="#"th:attr="skuId=${item.info.skuId},sessionId=${item.seckillSkuVo.promotionSessionId},code=${item.seckillSkuVo.randomCode}">立即抢购</a></p> package com.saodai.saodaimall.product.vo;import lombok.Data;import java.math.BigDecimal;/*** 秒杀商品的信息**/@Datapublic class SeckillSkuVo {/*** 活动id*/private Long promotionId;/*** 活动场次id*/private Long promotionSessionId;/*** 商品id*/private Long skuId;/*** 秒杀价格*/private BigDecimal seckillPrice;/*** 秒杀总量*/private Integer seckillCount;/*** 每人限购数量*/private Integer seckillLimit;/*** 排序*/private Integer seckillSort;//当前商品秒杀的开始时间private Long startTime;//当前商品秒杀的结束时间private Long endTime;//当前商品秒杀的随机码private String randomCode;}(1)判断登录状态,只有登录了才可以抢购
(2)发请求"http://seckill.saodaimall.com/kill?killId=" + killId + "&key=" + code + "&num=" + num
例如http://seckill.saodaimall.com/kill?killId=4-39&key=
9b4b6e45923b4d88ae9739a5240d0459&num=1
其中killId是秒杀Id(其实就是封装成redis中的格式),key是随机码,num是抢购数量
// 立即抢购之前必须登录$(".seckill").click(function () {var isLogin = [[${session.loginUser != null}]]; if (isLogin) {var killId = $(this).attr("sessionid") + "-" + $(this).attr("skuid");var code = $(this).attr("code");var num = $("#productNum").val();location.href = "http://seckill.saodaimall.com/kill?killId=" + killId + "&key=" + code + "&num=" + num;} else {alert("秒杀请先登录");}return false;});流程:
1、绑定hashMap操作redis,绑定的Hash值为seckill:skus
2、根据killId获取当前sku商品的详细信息,也就是获取这个key对应的value(这个killId其实就是redis中的key,格式为4-47)
3、判断当前这个秒杀商品是否在秒杀活动时间区间内(效验时间的合法性)
4、效验随机码是否和缓存里的一致
5、判断信号量是否大于0(也就是看有没有库存),并且买的数量不能超过秒杀商品数量的限制
6、进行幂等性处理(验证这个人是否已经买过了,防止有人每次的确只买限制次数的一个,但是他买多次,相当于发多次请求)
7、占坑成功后进行信号量处理(其实就是减信号量,表示业务为减库存)
8、快速生成一个秒杀订单号
9、封装SeckillOrderTo对象,然后发给RabbitMQ队列
流程:
1、封装订单实体类
1>封装秒杀的信息到订单里
2>保存订单到数据库
2、封装秒杀订单项
1>封装秒杀信息
2>远程调用查询spu信息来封装到秒杀订单项
3>远程调用查询sku信息来封装到秒杀订单项
4>保存秒杀订单项到数据库
/*** 创建秒杀单*/@Overridepublic void createSeckillOrder(SeckillOrderTo orderTo) {//封装订单实体类OrderEntity orderEntity = new OrderEntity();// 保存秒杀信息(getOrderSn这个订单号是秒杀的订单号)orderEntity.setOrderSn(orderTo.getOrderSn());orderEntity.setMemberId(orderTo.getMemberId());orderEntity.setCreateTime(new Date());//秒杀总共价格BigDecimal totalPrice = orderTo.getSeckillPrice().multiply(BigDecimal.valueOf(orderTo.getNum()));//应该支付的价格orderEntity.setPayAmount(totalPrice);//CREATE_NEW(0,"待付款")orderEntity.setStatus(OrderStatusEnum.CREATE_NEW.getCode());//保存秒杀订单this.save(orderEntity);//保存秒杀订单项信息OrderItemEntity orderItem = new OrderItemEntity();orderItem.setOrderSn(orderTo.getOrderSn());//秒杀总共价格orderItem.setRealAmount(totalPrice);//秒杀商品购买的数量orderItem.setSkuQuantity(orderTo.getNum());//保存商品的spu信息//远程调用商品服务来查询商品信息R spuInfo = productFeignService.getSpuInfoBySkuId(orderTo.getSkuId());SpuInfoVo spuInfoData = spuInfo.getData("data", new TypeReference<SpuInfoVo>() {});orderItem.setSpuId(spuInfoData.getId());orderItem.setSpuName(spuInfoData.getSpuName());orderItem.setSpuBrand(spuInfoData.getBrandName());orderItem.setCategoryId(spuInfoData.getCatalogId());//保存sku的信息R skuInfoBySkuId = productFeignService.getSkuInfoBySkuId(orderTo.getSkuId());SkuInfoTo skuInfoTo = skuInfoBySkuId.getData("data",new TypeReference<SkuInfoTo>(){});orderItem.setSkuId(skuInfoTo.getSkuId());orderItem.setSkuPic(skuInfoTo.getSkuDefaultImg());orderItem.setSkuName(skuInfoTo.getSkuName());orderItem.setSkuPrice(skuInfoTo.getPrice());//赠送积分orderItem.setGiftIntegration(0);//赠送成长值orderItem.setGiftGrowth(0);//保存订单项数据orderItemService.save(orderItem);} package com.saodai.common.to.mq;import lombok.Data;import java.math.BigDecimal;/***秒杀订单类(秒杀商品成功后发给rabbit队列的封装类)**/@Datapublic class SeckillOrderTo {/*** 订单号*/private String orderSn;/*** 活动场次id*/private Long promotionSessionId;/*** 商品id*/private Long skuId;/*** 秒杀价格*/private BigDecimal seckillPrice;/*** 购买数量*/private Integer num;/*** 会员ID*/private Long memberId;}/*** 根据skuid查找sku对象*/@RequestMapping("/getSkuInfoBySkuId/{skuId}")//@RequiresPermissions("product:skuinfo:info")public R getSkuInfoBySkuId(@PathVariable("skuId") Long skuId){SkuInfoEntity skuInfo = skuInfoService.getById(skuId);return R.ok().setData(skuInfo);}