开发商城系统遇到的问题


开发商城系统遇到的问题

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

今天在写逻辑点击修改将内容回显的时候遇到了这个错误。
在这里插入图片描述
产生的原因:

  1. 函数递归调用层次过深,每调用一次,函数的参数、局部变量等信息就压一次栈,并且没有及时出栈。
  2. 局部静态变量体积太大

我这次是因为在写后端逻辑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插入数据,因为这张表需要attrIdattrGroupId。我就很纳闷。

我最后发现这个规格参数属于商品属性,而attrGroupId是属于属性分组这个实体类的。也就是说我要添加一个新的规格参数,首先我要去属性分组新建一个这个分组。才能拿到attrGroupId
在这里插入图片描述
我们再来捋一下。首先你要添加一个规格参数,也就是添加一个商品的属性,你要先选择给那个商品添加。比如这次我们要添加一个属性:上市时间
在这里插入图片描述
,当然这样还不行,我们既然要给手机这个分类添加属性:上市时间,那么就要先看看手机这个分类有没有对应的属性分组。有才能够把属性添加到属性分组中去,否则你属性分组都没,何谈属性分组id(attrGroupId)
在这里插入图片描述

7、判断集合型的id不为空的问题

项目中有一处需要判断id不为空,以下是这个id:

List<Long> attrIds = xxx

可以看到这一个集合,于是我便用下面的方式来判断它不为空。

if(attrIds!=null||attrIds.size()>0)

但是这是错误的!具体原因没有找到,我猜测可能是有一些为空的条件被我漏掉了。
解决:使用以下方法

if(!CollectionUtils.isEmpty(attrIds))

8、启动服务比较多,内存比较吃紧

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


文章作者: fFee-ops
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fFee-ops !
评论
  目录