目录

Day5  制作SKU

1. 制作SKU

2. 多表查询如何写?

3. 制作SKU

4. Thymeleaf

Day06 商品详情

1. 获取分类信息

2. 获取最新价格信息

3. 获取销售信息

4. 实现商品切换

5. 获取海报信息

6. Sku对应的平台属性 -- 规格参数

7. 创建远程feign 调用

8. service-item 汇总数据

9. 搭建 web、访问测试

Day07 Redis缓存、redssion分布式锁

1. 项目如何优化?

2. 讲讲 redis 主从、集群原理

3. 缓存穿透、缓存击穿、缓存雪崩 ★

4. 本地锁 -- Gateway网关配置

5. redis 分布式锁

6. redisson 解决分布式锁

7. 锁机制


Day5  制作SKU

1. 制作SKU

SPU:一组可复用易检索的标准化信息集合

SKU:每种商品均对应唯一的编号

sku 图片 都应该是基于 SPU 选择的!

sku 应该有属于自己的url 地址!

SKU 相关表结构:
spuInfo:
id,spuName,category3Id,tmId,createTime,updateTime,isDelete
1, 红旗手机, 61  ,       1

skuInfo:    库存单元表
id,skuName,spuId,price,category3Id,defaultImage,isSale,createTime,updateTime,isDelete
1 ,红旗1  , 1                         0/1
2 ,红旗2  , 1 
skuImage:    库存单元图片表
id,imgName,skuId,imgUrl,createTime,updateTime,isDelete
1,    xx1        1      http://
2,    xx2        1
3,    xx3        1

sku 与 销售属性值Id 有关系么?
skuSaleAttrValue:    sku 与 销售属性值Id 中间表    spuSaleAttrValue
id,skuId,spuSaleAttrId, spuSaleAttrValueId,createTime,updateTime,isDelete
1, 1 ,        1,                1
2, 1 ,        2,                1

sku 与 平台属性值Id 有关系么?    
skuAttrValue:    sku 与 平台属性值Id 中间表    baseAttrValue 
id,skuId,saleAttrId, saleAttrValueId,createTime,updateTime,isDelete
1, 1 ,        1,                1
2, 1 ,        2,                1

商品数量:会单独有一个库存系统
        skuId ,    skuNum
            1,    1000
            2,    10000

2. 多表查询如何写?

        1. 找表 (字段从哪些表中去获取)

        2. 找关联关系:主外键、名字相同的、名字不同含义相同...

        3. 根据业务添加筛选条件,分组,排序,分页...

        4. sql调优:小表Join大表、使用索引覆盖,避免全盘扫描...

3. 制作SKU

为什么要回显这个功能? 
在商品检索页面的时候,能够保证用户可以通过平台属性值Id 进行检索出 sku

功能分析:
1. 回显平台属性与平台属性值
        http://localhost/admin/product/attrInfoList/2/13/61

2. 回显销售属性与销售属性值
        http://localhost/admin/product/spuSaleAttrList/12

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper SYSTEM "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--namespace 定义接口的全路径-->
<mapper namespace="com.atguigu.gmall.product.mapper.SpuSaleAttrMapper"><resultMap id="SpuSaleAttrMap" type="com.atguigu.gmall.model.product.SpuSaleAttr"autoMapping="true"><id property="id" column="id"></id><!--配置1:n--><collection property="spuSaleAttrValueList" ofType="com.atguigu.gmall.model.product.SpuSaleAttrValue"autoMapping="true"><id property="id" column="sale_attr_value_id"></id></collection></resultMap><!--如果有很多字段名需要复用,可以使用sql片段标签--><sql id="spuSql">ssa.id,ssa.spu_id,ssa.base_sale_attr_id,ssa.sale_attr_name,ssav.id sale_attr_value_id,ssav.sale_attr_value_name</sql><select id="selectSpuSaleAttrList" resultMap="SpuSaleAttrMap">select <include refid="spuSql"></include>from spu_sale_attr ssa join spu_sale_attr_value ssavon ssa.spu_id = ssav.spu_idand ssa.base_sale_attr_id = ssav.base_sale_attr_idwhere ssa.spu_id = #{spuId}and ssa.is_deleted = 0and ssav.is_deleted = 0</select></mapper>

3. 回显spuImage!
select * from spu_image where spu_id = ? and is_delete = 0;
skuImage 都是从spuImage 中选择的!

http://localhost/admin/product/spuImageList/12
4. 保存skuInfo
    http://localhost/admin/product/saveSkuInfo

(需操作4张表)
测试:
    小米:
        skuId = 25 小米(MI)CC9 屏幕指纹美颜自拍手机 仙女渐变色(美图定制版)6GB+128GB
        skuId = 26 小米(MI)CC9 屏幕指纹美颜自拍手机 仙女渐变色(美图定制版)6GB+64GB
    华为:
        skuId = 27    荣耀(HONOR) 荣耀V30 PRO 双模5G全网通手机 麒麟990处理器 V30 Pro【幻夜星河】 全网通(8GB+256GB)
        skuId = 28    荣耀(HONOR) 荣耀V30 PRO 双模5G全网通手机 麒麟990处理器 V30 Pro【冰岛幻境】 全网通(8GB+256GB)

5. 根据分类Id 查询skuInfo 列表
Request URL: http://localhost/admin/product/list/1/10?category3Id=61
/admin/product/list/{page}/{limit}

select * from skuInfo where category3_id = ? and is_delete = 0 order by id desc limit 0, 10;   mysql;

6. 商品上架- 下架:
http://localhost/admin/product/onSale/28
http://localhost/admin/product/cancelSale/22

7. 修改SKU (多表联查) 课后

    //通过ID回显SkuInfo@Overridepublic SkuInfo getSkuInfoById(Long skuId) {//skuImageListList<SkuImage> skuImageList = skuImageMapper.selectList(new QueryWrapper<SkuImage>().eq("sku_id", skuId));//skuAttrValueList (Join 多表联查)List<SkuAttrValue> skuAttrValueList = skuAttrValueMapper.selectBySkuId(skuId);//skuSaleAttrValueList (Join 多表联查)List<SkuSaleAttrValue> skuSaleAttrValueList = skuSaleAttrValueMapper.selectBySkuId(skuId);//skuInfoSkuInfo skuInfo = skuInfoMapper.selectById(skuId);skuInfo.setSkuSaleAttrValueList(skuSaleAttrValueList);skuInfo.setSkuImageList(skuImageList);skuInfo.setSkuAttrValueList(skuAttrValueList);return skuInfo;}
    //修改SKU@Override@Transactional(rollbackFor = Exception.class)public void updateSkuInfo(SkuInfo skuInfo) {skuInfoMapper.updateById(skuInfo);Long skuId = skuInfo.getId();//先删除,后新增skuAttrValueMapper.delete(new QueryWrapper<SkuAttrValue>().eq("sku_id",skuId));skuImageMapper.delete(new QueryWrapper<SkuImage>().eq("sku_id",skuId));skuSaleAttrValueMapper.delete(new QueryWrapper<SkuSaleAttrValue>().eq("sku_id",skuId));//复用新增,插入skuInfo时判断是否存在idthis.saveSkuInfo(skuInfo);}

4. Thymeleaf

渲染:Thymeleaf ---> 使用!
th:text        显示文本
th:value    给 value 属性赋值 ,在表单提交的时候,都是提交的value 值

<form action="login" method="get"><input type="text" value="admin" name="userName"/><input type="password" value="123456" name="pwd"/><input type="submit" value="提交"/>
</form>

点击提交的时候,会将value 属性值 传递到后台

@RequestMapping("login")
public void login(String userName,String pwd){userName = admin;pwd = "123456"
}

th:if        符合判断:
th:unless    不符合判断:
th:each        循环遍历集合
th:include    内嵌页{页面,【css,js,图片】--- 静态资源 springmvc }
th:utext -- 页面解析样式!
th:session    接收session数据
th:href        超链接

扩展:存储数据对象使用!
//    商品详情页面渲染使用!
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("id","1002");
hashMap.put("stuName","atguigu");
hashMap.put("stuAge","9");

model.addAllAttributes(hashMap);

配置:
1.    Thymeleaf 有默认的前缀,后缀

2.    Thymeleaf 还可以开启热部署,修改页面之后,不需要重启服务!
spring.thymeleaf.cache=false

1.    Thymeleaf 有默认的前缀,后缀

2.    Thymeleaf 还可以开启热部署,修改页面之后,不需要重启服务!
spring.thymeleaf.cache=false

Day06 商品详情

 功能划分:
1、    分类数据的获取!

2、    skuInfo 的基本信息,skuName,defaultImage,weight

3、    价格单独查询 -- 保证价格实时性!

4、    skuImage 集合

5、    销售属性回显并锁定!

6、    点击不同的销售属性值实现切换功能!

7、    查询海报信息!

8、    规格与包装!
        包含商品的平台属性数据!
        暂时使用商品的平台属性进行渲染!

----------------------------------------------------------------------------------------------                    
9、    商品评价 远程调用 spuId;

10、  手机社区BBS 论坛!

模板划分: 
web-all :页面渲染

service-item : 商品详情微服务

service-product : 商品数据提供微服务

server-gateway :  接收用户所有的请求: http://item.gmall.com/28.html 
            解析域名    item.gmall.com    --->web-all !

server-gateway ---> web-all ---> service-item{汇总数据使用map 进行存储!} ---> service-product{查询数据}

从分布式微服务来讲,service-item 汇总数据不能省。

1. 获取分类信息

sku是挂在三级分类下面的,我们的分类信息分别在base_category1、base_category2、base_category3这三张表里面,目前需要通过sku表的三级分类id获取一级分类名称、二级分类名称和三级分类名称

解决方案:

我们可以建立一个视图(view),把三张表关联起来,视图id就是三级分类id,这样通过三级分类id就可以查询到相应数据,效果如下

create or replace view base_category_view as
select c3.id id,c1.id c1_id,c1.name c1_name,c2.id c2_id,c2.name c2_name,c3.id c3_id,c3.name c3_name
from base_category1 c1 join  base_category2 c2
on c1.id = c2.category1_id
join base_category3 c3
on c2.id = c3.category2_id;
    public BaseCategoryView getCategoryViewByCategory3Id(Long category3Id) {//select * from base_category_view where id = 61/*#使用一条语句:view视图:随着原数据的变化而变化 id = category3Id# 如果数据频繁更变,开发组中明确规定不能使用视图*/return baseCategoryViewMapper.selectById(category3Id);}

2. 获取最新价格信息

    public BigDecimal getSkuPrice(Long skuId) {//SkuInfo skuInfo = skuInfoMapper.selectById(skuId);QueryWrapper<SkuInfo> wrapper = new QueryWrapper<>();wrapper.eq("id",skuId);//设置指定查询字段wrapper.select("price");SkuInfo skuInfo = skuInfoMapper.selectOne(wrapper);if(skuInfo!=null){return skuInfo.getPrice();}return new BigDecimal("0");}

3. 获取销售信息

查询销售属性+销售属性值;查询skuId 对应的销售属性值Id 是谁;将a,b 结合!

#单独限制某一张表,条件放在on后面
selectssa.id,ssa.spu_id,ssa.base_sale_attr_id,ssa.sale_attr_name,ssav.id sale_attr_value_id,ssav.sale_attr_value_name,sv.sku_id,if(sv.sku_id is null,0,1) is_checked
from spu_sale_attr ssa join spu_sale_attr_value ssavon ssa.spu_id = ssav.spu_idand ssa.base_sale_attr_id = ssav.base_sale_attr_id
left join sku_sale_attr_value svon sv.sale_attr_value_id = ssav.idand sv.sku_id = ?
where ssa.spu_id = ?and ssa.is_deleted = 0and ssav.is_deleted = 0and (sv.is_deleted = 0 or sv.is_deleted is null)
order by ssav.base_sale_attr_id,ssav.id;
    <!--查询销售信息--><select id="getSpuSaleAttrListCheckBySku" resultMap="SpuSaleAttrMap">select<include refid="spuSql"></include>,sv.sku_id,if(sv.sku_id is null,0,1) is_checkedfrom spu_sale_attr ssa join spu_sale_attr_value ssavon ssa.spu_id = ssav.spu_idand ssa.base_sale_attr_id = ssav.base_sale_attr_idleft join sku_sale_attr_value svon sv.sale_attr_value_id = ssav.idand sv.sku_id = #{skuId}where ssa.spu_id = #{spuId}and ssa.is_deleted = 0and ssav.is_deleted = 0and (sv.is_deleted = 0 or sv.is_deleted is null)order by ssav.base_sale_attr_id,ssav.id</select>

4. 实现商品切换

用户通过点击不同的销售属性值,来切换到不同的skuId

思路:在后台将所有的销售属性值Id 与 skuId 进行组合
3742|3745 = 28、3743|3745 = 27
{"3742|3745":28,"3743|3745":27} --- Json 对象
必须是同一组:skuId , 过滤条件 必须是同一个商品 spuId

# 3746|3744  3747|3744
# group_concat(要拼接的字段 排序字段 分隔符);不写默认,
# 排序字段复杂一点,可以按照销售id排序,切换的时候要保证与回显数据一致,可能会导致数据拼接或切换顺序错乱
select group_concat(ssav.sale_attr_value_id order by ssav.id desc separator '|')value_ids,sku_id
from sku_sale_attr_value ssav
where ssav.spu_id = ?
group by sku_id;
    <resultMap id="SkuSaleAttrValueMap" type="java.util.Map" autoMapping="true"></resultMap><!--实现商品切换:根据spuId查询map集合属性--><select id="getSkuValueIdsMap" resultMap="SkuSaleAttrValueMap">select group_concat(ssav.sale_attr_value_id order by id separator '|') value_ids,sku_idfrom sku_sale_attr_value ssavwhere ssav.spu_id = #{spuId}group by sku_id</select>

5. 获取海报信息

    public List<SpuPoster> findSpuPosterBySpuId(Long spuId) {List<SpuPoster> spuPosterList = spuPosterMapper.selectList(new QueryWrapper<SpuPoster>().eq("spu_id", spuId));return spuPosterList;}

6. Sku对应的平台属性 -- 规格参数

根据 skuId 平台属性数据:---- 规格参数

select bai.id,bai.attr_name,bai.category_id,bai.category_level,bav.id attr_value_id,bav.value_name
from base_attr_info bai join base_attr_value bav
on bai.id = bav.attr_id
join sku_attr_value sav
on sav.value_id = bav.id and sav.sku_id = ?
    <!--根据skuId查询平台属性数据--><select id="selectAttrList" resultMap="baseAttrInfoMap">select bai.id,bai.attr_name,bai.category_id,bai.category_level,bav.id attr_value_id,bav.value_namefrom base_attr_info bai join base_attr_value bavon bai.id = bav.attr_idjoin sku_attr_value savon sav.value_id = bav.id and sav.sku_id = #{skuId}</select>

7. 创建远程feign 调用

8. service-item 汇总数据

@Service
public class ItemServiceImpl implements ItemService {@Qualifier("com.atguigu.gmall.product.client.ProductFeignClient")@Autowiredprivate ProductFeignClient productFeignClient;//根据skuId 获取渲染数据@Overridepublic Map<String, Object> getItem(Long skuId) {HashMap<String, Object> map = new HashMap<>();// 获取商品的基本信息 + 商品图片列表SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);//获取分类数据BaseCategoryView categoryView = productFeignClient.getCategoryView(skuInfo.getCategory3Id());//获取价格BigDecimal skuPrice = productFeignClient.getSkuPrice(skuId);//获取销售属性+属性值+锁定List<SpuSaleAttr> spuSaleAttrList = productFeignClient.getSpuSaleAttrListCheckBySku(skuId, skuInfo.getSpuId());//获取海报List<SpuPoster> spuPosterList = productFeignClient.getSpuPosterBySpuId(skuInfo.getSpuId());//获取数据,转换 json 字符串Map skuValueIdsMap = productFeignClient.getSkuValueIdsMap(skuInfo.getSpuId());String strJson = JSON.toJSONString(skuValueIdsMap);//获取商品规格参数--平台属性List<BaseAttrInfo> attrList = productFeignClient.getAttrList(skuId);if(!CollectionUtils.isEmpty(attrList)){List<HashMap<String, Object>> attrMapList = attrList.stream().map(baseAttrInfo -> {// 为了迎合页数据存储,定义一个map集合HashMap<String, Object> hashMap = new HashMap<>();hashMap.put("attrName", baseAttrInfo.getAttrName());hashMap.put("attrValue", baseAttrInfo.getAttrValueList().get(0).getValueName());return hashMap;}).collect(Collectors.toList());// 保存规格参数:只需要平台属性名:平台属性值map.put("skuAttrList",attrMapList);}map.put("skuInfo",skuInfo);map.put("categoryView",categoryView);map.put("price",skuPrice);map.put("spuSaleAttrList",spuSaleAttrList);map.put("spuPosterList",spuPosterList);map.put("valuesSkuJson",strJson);return map;}}

9. 搭建 web、访问测试

访问测试: http://item.gmall.com/22.html

Loc锁 synchronized 区别?

线程间如何通信?

Day07 Redis缓存、redssion分布式锁

1. 项目如何优化?

使用各种中间件

TomCat默认并发500,设置两个参数;服务器带宽

1. 架构优化:单体架构-垂直架构-rpc-soa-分布式微服务;时间成本(学习-代码重构)

2. 增加服务器:各种集群

mysql集群:mycat 垂直分库(按照业务) 水平分表(安装某个字段)

Redis主从复制+集群

3. 减少io:减少用户访问次数 -- redis缓存;

索引优化:explain: all --> index ---> 【range ---> ref】---> er_ref ---> const --->sysetm

        单表:全值匹配、最佳左前缀、否定会导致索引失效 != <> is not null、范围右边会失效、like

        关联:被驱动表建立索引,不用内连接

        子查询:改成 A left join B where A.id is null;

        分组-排序:无过滤不索引;顺序错,必排序;方向反,必排序

        建议:不要写 * ,尽量使用覆盖索引;减少回表,尽量使用索引下推

4. 减少同步:减少同步操作 -- mq异步解耦

5. redis优化

2. 讲讲 redis 主从、集群原理

集群原理:

16384个槽 (slot) 与 key进行运算:crc32 算法 获取到一个值,根据这个值决定在那一组节点上存放数据。
redis - 哨兵 主从复制原理:
1. 从机发送复制请求 sync 异步命令
2. 全量复制:主机进行bgsave: 拍个快照把当前所有状态全都发过去
3. 异步增量复制:后续将写入或修改命令 发送给从机!

3. 缓存穿透、缓存击穿、缓存雪崩 ★

缓存穿透:查询一个不存在的数据,由于缓存不存在,直接去查询数据库,但是数据库也无此记录,所以我们没有将null写入缓存。但这导致每次请求都会访问数据库,别人可以利用不存在的 key频繁攻击我们的应用。

解决方案缓存null对象 或 使用布隆过滤器

缓存击穿:是指对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:如果这个key在大量请求同时进来之前正好失效,那么所有对这个key的数据查询都落到DB,我们称为缓存击穿。

解决方案redis;redisson 分布式锁   在分布式的环境下,应使用分布式锁来解决,分布式锁的实现方案有多种,比如使用Redis的setnx、使用Zookeeper的临时顺序节点等来实现

缓存雪崩:Redis宕机;或在设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。

解决方案

1. 事前:redis高可用,主从+哨兵;事中:本地缓存ehcache+限流组件Hystrix;防止宕机;事后:redis持久化 快速恢复缓存数据

2. 原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

与缓存雪崩的区别:

1. 击穿是一个热点key失效

2. 雪崩是很多key集体失效

4. 本地锁 -- Gateway网关配置

总结:本地锁的局限性 --- 分布式微服务集群部署时,锁不住资源!

routes:
- id: service-product
  uri: lb://service-product
  predicates:

    - Path=/*/product/** # 路径匹配
小知识点:port 的优先级,nacos 的优先级高于 运行类配置 高于配置文件!

Gateway网关负载均衡 默认轮询

改网关访问这三个微服务:
    8206
    8216
    8226
ab  -n 5000 -c 100 http://192.168.200.1/admin/product/test/testLock
    synchronized 锁不住资源!

5. redis 分布式锁

分布式锁实现的解决方案

1. 基于数据库实现分布式锁;IO限制
2. 基于缓存(Redis等) 性能高 基于io

setnx key value; 判断当前这个key是否存在,存在则不生效;

Boolean result = redisTemplate.opsForValue().setIfAbsent("lock","ok")
3. 基于Zookeeper 安全性高

ZNode节点;持久化节点 非持久化节点,将节点看做锁

性能redis最高;可靠性zookeeper最高

Redis 分布式锁,电商方式         

1、setnx key value:容易出现死锁;需要清空锁

2、设置锁并加默认的过期时间:多线程误删锁
        expire key timeout             不具备原子性!
        setex  key timeout value    ---    key 与 过期时间具有原子性!

redis 2.6.12 版本以后:setnx + setex 命令整合
        set key value ex/px timeout nx/xx;    具有原子性
NX :键不存在时,才对键进行设置操作;XX :键已经存在时,才对键进行设置操作。

3、设置一个uuid 防止误删锁:删除锁缺乏原子性

4、使用lua 脚本保证删除锁具有原子性:集群情况下锁不住资源

lock,unlock 可能产生锁死,不需等待自旋机制;trylock可设定过期时间,需要等待自旋机制。

//  这个脚本只在客户端传入的值和键的口令串相匹配时,才对键进行删除
String scriptText = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
DefaultRedisScript defaultRedisScript = new DefaultRedisScript<>();
defaultRedisScript.setResultType(Long.class);
defaultRedisScript.setScriptText(scriptText);
//  第一个参数:defaultRedisScript 第二个参数:键值 第三个参数:口令串
this.redisTemplate.execute(defaultRedisScript, Arrays.asList("lock"),uuid);

5、redisson:Redisson 提供了使用Redis的最简单和最便捷的方法,Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

6. redisson 解决分布式锁

官方文档地址:Home · redisson/redisson Wiki · GitHub

单节点:redisson - Lock、TryLock

集群:redisson - redLock

1、最常用的方式:lock.lock();lock.unlock();

redisson : 有个宠物 --- 作用防止锁死状态!  --- 监控redis, 如果redis 实例宕机了,则会默认设置锁的有效期,默认是30秒钟; 也可以通过 Config.lockWatchdogTimeout 设置。
    
2、在加锁的时候自定义锁的有效期:加锁以后10秒钟自动解锁
lock.lock(10, TimeUnit.SECONDS);

3、尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     //    业务逻辑
   } finally {
       lock.unlock();
   }
}else {

   //等待、自旋

}

底层源码:lua脚本,AQS

7. 锁机制

可重入锁:某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。

公平锁:按照申请锁的顺序去获得锁,线程会直接进入队列,先进先出。

连锁:若干锁同时上锁成功才算成功。new RedissonMultiLock(lock...)

红锁:大部分节点上加锁就算成功。new RedissonRedLock(lock...)

读写锁:读读可并发,其他都不可并发

信号量(Semaphore):多线程访问多资源,控制资源量;单资源加锁即可

闭锁(CountDownLatch倒计时线程控制):倒计时线程控制;减少计数为0时执行。

Day137-139.尚品汇:制作SKU、商品详情、项目优化:Redis缓存、redssion分布式锁相关推荐

  1. Day140-142.尚品汇:AOP+Redis缓存+redssion分布式锁、CompletableFuture异步编排、首页三级分类展示、Nginx静态代理

    目录 Day08 一.获取商品详情 加入缓存 二.全局缓存:分布式锁与aop 整合 三.布隆过滤器 四.CompletableFuture 异步编排 jdk1.8 Day09 1. 将item 改为多 ...

  2. 尚品汇_第4章_ 商品spu保存

    尚品汇第四章: 商品spu保存 文章目录 尚品汇第四章: 商品spu保存 一.spu相关业务介绍 1.1 销售属性 1.2 spu数据结构图 2.2 创建接口ManageService 2.3 创建实 ...

  3. 尚品汇_第3章_平台属性管理

    尚品汇_第3章__平台属性管理 文章目录 尚品汇_第3章__平台属性管理 一.商品的基本知识 1.1 基本信息-分类 1.2 基本信息-平台属性 1.3 基本信息-销售属性与销售属性值 1.4 基本信 ...

  4. 尚硅谷尚品汇_后台管理项目

    vueProject_尚品汇后台管理 项目源码 文章目录 vueProject_尚品汇后台管理 login/out模块 product模块 login/out模块 .env.development . ...

  5. vue实战项目-电商商城前台-(学习尚硅谷的)尚品汇

    文章目录 最好使用视频上的账号密码,13700000000 密:111111 最新服务端接口地址:http://gmall-h5-api.atguigu.cn 脚手架使用 1.创建项目 2.脚手架默认 ...

  6. ① 尚品汇的后台管理系统【尚硅谷】【Vue】

    后台管理系统项目简介 什么是后台管理系统项目? 在前端领域当中,开发后台管理系统项目,并非是Java,PHP等后台语言项目 在前面课程当中,我们已经开发了一个项目[尚品汇电商平台项目],这个项目主要针 ...

  7. 尚品汇后台管理项目(Vue)

    简介 1:什么是后台管理系统项目? 注意:前端领域当中,开发后台管理系统项目,并非是java.php等后台语言项目. 在前面课程当中,我们已经开发了一个项目[尚品汇电商平台项目],这个项目主要针对的是 ...

  8. 基于 Vue2 的尚品汇电商前后台项目

    开发时间:2022.11.07-2022.12.07 前台项目 后台管理 atguigu-store-frontend atguigu-store-backend 文章目录 一.快速开始 二.系统概述 ...

  9. vue尚品汇商城项目-day00【项目介绍:此项目是基于vue2的前台电商项目和后台管理系统】

    文章目录 本人其他相关文章链接 项目介绍:此项目是基于vue2的前台电商项目和后台管理系统 此项目为在线电商Web App (SPA) 包括首页, 搜索列表, 商品详情, 购物车, 订单, 支付, 用 ...

最新文章

  1. 人工智能落地之路:从概念验证到产品
  2. Makefile常用信息查询页
  3. unity fixedupdate_unity相关
  4. P4899 [IOI2018] werewolf 狼人(kruskal 重构树 + 主席树)
  5. 知方可补不足~数据库名称和数据库别名不同了怎么办
  6. (原創) 何谓可读性高的程序? (C/C++)
  7. JS删除数组中某一项或几项的方法汇总
  8. Redis--安装与配置(Linux与Windows)
  9. Android adb不是内部或外部命令 问题解决
  10. Java多线程300毫秒_Java多线程小程序(输出每个线程的毫秒级时间)-Go语言中文社区...
  11. 音视频基础1:H264、H265、MPEG-4、VP8、VP9编码基础知识
  12. 手写文本 matlab 识别,手写汉字识别matlab
  13. Unity打包篇:能够解决Unity打包Gradle遇到的所有问题方法整合!(持续更新中!)
  14. 我如何启动任何.NET Core Web API项目
  15. 计算机内存数值存储方式(原码、反码、补码)
  16. RV1126 Linux 以太网MAC PHY 芯片8201f gmac dts配置
  17. ASM、AAM算法介绍
  18. 债券价格和到期收益率的关系_债券价格、到期收益率与票面利率之间的关系是什么?...
  19. 大神偷偷收藏的7个自学网站,质量高且免费,请低调使用
  20. 解决Leaflet.draw中polyline绘制无法结束的问题

热门文章

  1. Filmic Tonemapping Operators
  2. ASIC设计开发流程
  3. Gromacs中trr文件转换为可读文件方法
  4. Win10下安装docker并拉取redis镜像启动
  5. 【imessage苹果推信】软件安装苹果虚拟机推群发UDID和App的Bundle Id生成deviceToken
  6. 开启联想电脑管家电池养护模式的操作步骤
  7. 极其好用的PC软件推荐
  8. C++ 队列的创建和基本操作
  9. 计算机网络结课答辩,计算机网络技术结课论文.doc
  10. 腾讯AI Lab涂兆鹏:如何提升神经网络翻译的忠实度 | 附PPT + 视频