开发商城系统遇到的问题
- 1、文件存储的问题
- 2、文件上传问题
- 3、属性分组-规格参数-销售属性-三级分类的关联关系
- 4、SPU、SKU
- 5、StackOverflowError: null
- 6、编写新增规格参数遇到的问题
- 7、判断集合型的id不为空的问题
- 8、启动服务比较多,内存比较吃紧
1、文件存储的问题
单体应用上传只需要简单的传到一个地方存储起来,以后要用的时候再从那个地方拿就可以了。
但是分布式应用不行。分布式应用如果像下图一样,只存在一个地方。我们假如部署了三台服务器,第一次来到一号服务器,存放图片。下次如果访问的还是1号服务器,那当然可以拿到图片。但是由于负载均衡,来到2号服务器,那么就拿不到了。所以这种方式是行不通的。
所以我们选择第三种方式。无论哪个服务器发起上传请求,最终都上传到一个文件存储系统,这个系统可以是自建服务器,也可以是阿里云等。
2、文件上传问题
此次项目选择阿里云对象存储
①假设像下图那么上传,每次都要经过我们自己的服务器,由自己的服务器带上密码进行上传文件流等,虽然安全,但是性能消耗大。
②不经过自己的服务器,直接用前端进行上传,但是因为上传到阿里云需要密码,所以我们就要把密码写在前端JS
中,安全性非常低。
③上传所需的账号密码还是存在自己的服务器,前端向自己的服务器要到一个上传策略,可以理解为令牌(是由存在服务器的账号密码生成的),前端再带着这个签名去上传,这样自己的服务器不用上传文件流,只需要返回一个令牌就行了。
3、属性分组-规格参数-销售属性-三级分类的关联关系
基本概念:
同一SPU的基本属性是相同的,比如Iphone11的重量、大小等。不管颜色是什么都是一样的。
而销售属性就是颜色、内存、容量等。比如iphone11的白色比黑色贵
比如进入到商城页面,就有一个分类为手机,手机有哪些属性呢?就可以到属性分组表中查看, 有两组属性,一组为主体、一组为屏幕。而主体、屏幕是两个属性分组,那么它们下面具体有些什么属性?可以到属性表中查看。
用了一张属性分组&属性关联表
来把属性分组和具体属性两张表关联起来。
4、SPU、SKU
spu: 商品聚合信息的最小单位
sku: 商品的不可再分的最小单元
类目: 类目是一个树状结构的系统,大体上可以分成3-4级。如手机->智能手机->苹果手机类目,在这里面,手机是一级类目,苹果手机是三级类目,也是叶子类目。
SPU:苹果6(商品聚合信息的最小单位),如手机->苹果手机->苹果6,苹果6就是SPU。
SKU:苹果6 土豪金 16G (商品的不可再分的最小单元)。
从广义上讲,类目>SPU>SKU。
SPU用来决定规格参数的值,SKU用来决定销售属性的值
SPU-SKU-属性表
即SPU为1的商品 iPhone11有两个属性,分别是2:像素、1:网络。
像素的属性是3000万,网络的属性是3、4、5G。
而销售属性值表主要就是这样:
有一个SPU是iPhone11,它有两个sku。每个sku都有内存、容量两个属性。
iphone11:
iphone11内存6G 容量128G。
iphone11内存4G 容量64G。
5、StackOverflowError: null
今天在写逻辑点击修改将内容回显的时候遇到了这个错误。
产生的原因:
- 函数递归调用层次过深,每调用一次,函数的参数、局部变量等信息就压一次栈,并且没有及时出栈。
- 局部静态变量体积太大
我这次是因为在写后端逻辑CategoryServiceImpl
里面的findPatentPath()
的时候出了问题。
/**
* 递归来找到目前分类id的所有父分类id。并且将目前id,和它的所有父分类id加入到list中进行保存
*
* @param catelogId 当前的分类id
* @param paths 用来保存完整的路径
* @return
*/
private List<Long> findPatentPath(Long catelogId, List<Long> paths) {
//收集当前节点id
paths.add(catelogId);
//用getById()拿到当前分类id的详细信息,其中就包含了它的父分类id
CategoryEntity cur = this.getById(catelogId);
if (cur.getParentCid() != 0) {
//递归去找它的所有父分类id
findPatentPath(catelogId, paths);
}
return (List<Long>) paths;
}
可以看到,我在递归调用的时候还是用的当前的catelogId,这样会导致这个方法变成死循环,因为一直都会查catelogId
的父分类id。
解决:递归findPatentPath(catelogId, paths);的时候把catlogId换成cur.getParentCid()
,也即当前遍历的节点为它的父节点了,这样就不会导致死循环了。
6、编写新增规格参数遇到的问题
后端代码都写好了,但是我发现前端传的attrGroupId
总是空的。导致不能给表pms_attr_attrgroup_relation
插入数据,因为这张表需要attrId
和attrGroupId
。我就很纳闷。
我最后发现这个规格参数属于商品属性
,而attrGroupId
是属于属性分组
这个实体类的。也就是说我要添加一个新的规格参数,首先我要去属性分组新建一个这个分组。才能拿到attrGroupId
。
我们再来捋一下。首先你要添加一个规格参数,也就是添加一个商品的属性,你要先选择给那个商品添加。比如这次我们要添加一个属性:上市时间
。
,当然这样还不行,我们既然要给手机这个分类添加属性:上市时间
,那么就要先看看手机这个分类有没有对应的属性分组
。有才能够把属性
添加到属性分组
中去,否则你属性分组都没,何谈属性分组id(attrGroupId)
。
7、判断集合型的id不为空的问题
项目中有一处需要判断id不为空,以下是这个id:
List<Long> attrIds = xxx
可以看到这一个集合,于是我便用下面的方式来判断它不为空。
if(attrIds!=null||attrIds.size()>0)
但是这是错误的!具体原因没有找到,我猜测可能是有一些为空的条件被我漏掉了。
解决:使用以下方法
if(!CollectionUtils.isEmpty(attrIds))