三 SPU、SKU、Lua、OpenResty

一 SPU与SKU

1.1 SPU与SKU概念

SPU = Standard Product Unit (标准产品单位,某款产品的公共属性)

  • 概念 : SPU 是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。

  • 通俗点讲,属性值、特性相同的货品就可以称为一个 SPU

    例如:华为P50 就是一个 SPU

SKU=stock keeping unit( 库存量单位,某款商品不同参数对应的商品信息)

  • SKU 即库存进出计量的单位, 可以是以件、盒、托盘等为单位。

  • SKU 是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。

  • 在服装、鞋类商品中使用最多最普遍。

    例如:华为P50 红色 64G 就是一个 SKU

2.2 表结构分析

tb_spu 表 (SPU表)

字段名称 字段含义 字段类型 字段长度 备注
id 主键 VARCHAR
sn 货号 VARCHAR
name SPU名 VARCHAR
caption 副标题 VARCHAR
brand_id 品牌ID INT
category1_id 一级分类 INT
category2_id 二级分类 INT
category3_id 三级分类 INT
template_id 模板ID INT
freight_id 运费模板id INT
image 图片 VARCHAR
images 图片列表 VARCHAR
sale_service 售后服务 VARCHAR
introduction 介绍 TEXT
spec_items 规格列表 VARCHAR
para_items 参数列表 VARCHAR
sale_num 销量 INT
comment_num 评论数 INT
is_marketable 是否上架 CHAR
is_enable_spec 是否启用规格 CHAR
is_delete 是否删除 CHAR
status 审核状态 CHAR

tb_sku 表(SKU商品表)

字段名称 字段含义 字段类型 字段长度 备注
id 商品id VARCHAR
sn 商品条码 VARCHAR
name SKU名称 VARCHAR
price 价格(分) INT
num 库存数量 INT
alert_num 库存预警数量 INT
image 商品图片 VARCHAR
images 商品图片列表 VARCHAR
weight 重量(克) INT
create_time 创建时间 DATETIME
update_time 更新时间 DATETIME
spu_id SPUID BIGINT
category_id 类目ID INT
category_name 类目名称 VARCHAR
brand_name 品牌名称 VARCHAR
spec 规格 VARCHAR
sale_num 销量 INT
comment_num 评论数 INT
status 商品状态 1-正常,2-下架,3-删除 CHAR

更简单的理解:
三 SPU、SKU、Lua、OpenResty_第1张图片

1.3 实现思路

前端传递给后端的数据格式 是一个spu对象和sku列表组成的对象

{
     
    "spu": {
     
      	"name": "这个是商品名称",
      	"caption": "这个是副标题",
		"brandId": 12,
		"category1Id": 558,
		"category2Id": 559,
		"category3Id": 560,
		"freightId": 10,
		"image": "http://www.qingcheng.com/image/1.jpg",
         "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg",
		"introduction": "这个是商品详情,html代码",
         "paraItems": {
     "出厂年份":"2019","赠品":"充电器"},
		"saleService": "七天包退,闪电退货",
		"sn": "020102331",
		"specItems":  {
     "颜色":["红","绿"],"机身内存":["64G","8G"]},
		"templateId": 42
	},
	"skuList": [{
     
		"sn": "10192010292",
         "num": 100,
      	 "alertNum": 20,
		"price": 900000,
         "spec": "{"颜色":"","机身内存":"64G"}",
         "image": "http://www.qingcheng.com/image/1.jpg",
         "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg",
		"status": "1",
		"weight": 130
	},
    {
     
		"sn": "10192010293",
         "num": 100,
      	 "alertNum": 20,
		 "price": 600000,
         "spec": {
     "颜色":"绿","机身内存":"8G"},
         "image": "http://www.qingcheng.com/image/1.jpg",
         "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg",
		"status": "1",
		"weight": 130
	}
  ]
}

1.4 代码实现

1.4.1 SPU与SKU列表的保存

(1)changgou_service_goods_api工程创建组合实体类Goods

/**
 * 商品组合实体类
 */
public class Goods implements Serializable {
     

    private Spu spu;
    private List<Sku> skuList;

    public Spu getSpu() {
     
        return spu;
    }

    public void setSpu(Spu spu) {
     
        this.spu = spu;
    }

    public List<Sku> getSkuList() {
     
        return skuList;
    }

    public void setSkuList(List<Sku> skuList) {
     
        this.skuList = skuList;
    }
}

(2)changgou_service_goods工程SpuService新增方法add(Goods goods)

    /***
     * 新增
     * @param goods
     */
    void add(Goods goods);

(3)changgou_service_goods工程SpuServiceImpl实现此方法

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private BrandMapper brandMapper;

    @Autowired
    private IdWorker idWorker;

    /**
     * 保存商品 SPU+SKU列表
     * @param goods 商品组合实体类
     */
    @Transactional
    @Override
    public void add(Goods goods) {
     
        //生成spuId
        long spuId = idWorker.nextId();
        //spuId放入SPU对象中
        goods.getSpu().setId(String.valueOf(spuId));
        //添加保存SPU数据
        spuMapper.insertSelective(goods.getSpu());

        //保存sku集合数据到数据库
        saveSkuList(goods);
    }

    /**
     * 保存sku列表
     * @param goods
     */
    private void saveSkuList(Goods goods){
     
        //获取spu对象
        Spu spu = goods.getSpu();
        //当前日期
        Date date = new Date();
        //获取品牌对象
        Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());
        //获取分类对象
        Category category = categoryMapper.selectByPrimaryKey(spu.getCategory3Id());
        //获取sku集合对象
        List<Sku> skuList = goods.getSkuList();
        if (skuList != null) {
     
            for (Sku sku : skuList) {
     
                //设置sku主键ID
                sku.setId(String.valueOf(idWorker.nextId()));
                //设置sku规格
                if (sku.getSpec() == null || "".equals(sku.getSpec())) {
     
                    sku.setSpec("{}");
                }
                //设置sku名称(商品名称 + 规格)
                String name = spu.getName();
                //将规格json字符串转换成Map
                Map<String, String> specMap = JSON.parseObject(sku.getSpec(), Map.class);
                if (specMap != null && specMap.size() > 0) {
     
                    for(String value : specMap.values()){
     
                        name += " "+ value;
                    }
                }

                sku.setName(name);//名称
                sku.setSpuId(spu.getId());//设置spu的ID
                sku.setCreateTime(date);//创建日期
                sku.setUpdateTime(date);//修改日期
                sku.setCategoryId(category.getId());//商品分类ID
                sku.setCategoryName(category.getName());//商品分类名称
                sku.setBrandName(brand.getName());//品牌名称
                skuMapper.insertSelective(sku);//插入sku表数据
            }
        }
    }

(3)修改SpuController的add方法

    /***
     * 新增数据
     * @param goods
     * @return
     */
    @PostMapping
    public Result add(@RequestBody Goods goods){
     
        spuService.add(goods);
        return new Result(true,StatusCode.OK,"添加成功");
    }

不管什么业务场景,涉及到多级分类的话,在分类表里,aprentID=0则表示是一级分类;

二 Lua

2.1 lua是什么

Lua 是一个小巧的脚本语言。它是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo三人所组成的研究小组于1993年开发的。 其设计目的是为了通过灵活嵌入应用程序中从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为开发独立应用程序的语言。Lua 有一个同时进行的JIT项目,提供在特定平台上的即时编译功能。

简单来说:

​ Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

lua 语言具有以下特性

  • 支持面向过程(procedure-oriented)编程和函数式编程(functional programming);
  • 自动内存管理;只提供了一种通用类型的表(table),用它可以实现数组,哈希表,集合,对象;
  • 语言内置模式匹配;闭包(closure);函数也可以看做一个值;提供多线程(协同进程,并非操作系统所支持的线程)支持;
  • 通过闭包和table可以很方便地支持面向对象编程所需要的一些关键机制,比如数据抽象,虚函数,继承和重载等。

应用场景

  • 游戏开发
  • 独立应用脚本
  • Web 应用脚本
  • 扩展和数据库插件如:MySQL Proxy 和 MySQL WorkBench
  • 安全系统,如入侵检测系统
  • redis中嵌套调用实现类似事务的功能
  • web容器中应用处理一些过滤 缓存等等的逻辑,例如nginx。

2.2 lua的安装

这里我们采用linux版本的安装

yum install -y gcc
yum install libtermcap-devel ncurses-devel libevent-devel readline-devel
curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz
tar -zxf lua-5.3.5.tar.gz
cd lua-5.3.5
make linux test
# 下边这个命令可以不执行
#make install

查看是否安装成功

lua
# 或者
lua -i

出现lua版本信息即成功
在这里插入图片描述
如果出现如下错误
三 SPU、SKU、Lua、OpenResty_第2张图片
则需要安装下边的依赖库

yum install libtermcap-devel ncurses-devel libevent-devel readline-devel

2.3 快速入门

创建hello.lua文件

vi hello.lua

内容为

print("hello");

保存。执行命令

lua hello.lua

输出为:

Hello

2.4 LUA的基本语法

  • lua有交互式编程和脚本式编程。

  • 交互式编程就是直接输入语法,就能执行。

  • 脚本式编程需要编写脚本,然后再执行命令,执行脚本才可以。

一般采用脚本式编程。(例如:编写一个hello.lua的文件,输入文件内容,并执行lua hell.lua即可)

2.4.1 注释

一行注释:两个减号是单行注释:

--

多行注释:

--[[
 多行注释
 多行注释
 --]]

2.4.2 关键字

关键字就好比java中的 break if else等等一样的效果。lua的关键字如下:

and break do else
elseif end false for
function if in local
nil not or repeat
return then true until
while

2.4.3 定义变量

全局变量,默认的情况下,定义一个变量都是全局变量,如果要用局部变量,需要声明为local.例如:

-- 全局变量赋值
a=1
-- 局部变量赋值
local b=2 

2.4.4 Lua中的数据类型

Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

数据类型 描述
nil 这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。
boolean 包含两个值:false和true。
number 表示双精度类型的实浮点数
string 字符串由一对双引号或单引号来表示
function 由 C 或 Lua 编写的函数
userdata 表示任意存储在变量中的C数据结构
thread 表示执行的独立线路,用于执行协同程序
table Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。

1.4.5 流程控制

如下:类似于if else

--[ 0 为 true ]
if(0) then
    print("0 为 true")
else
    print("0 不为true")
end

1.4.6 函数

lua中也可以定义函数,类似于java中的方法。例如:

--[[ 函数返回两个值的最大值 --]]
function max(num1, num2)

   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end

   return result; 
end
-- 调用函数
print("两值比较最大值为 ",max(10,4))
print("两值比较最大值为 ",max(5,6))

执行之后的结果:

两值比较最大值为     10
两值比较最大值为     6

两个点或者一个逗号,表示拼接,相当于java里的+

 .. : 拼接

三 SPU、SKU、Lua、OpenResty_第3张图片

2.4.7 require 函数

require 用于 引入其他的模块(后边讲模块的概念),类似于java中的类要引用别的类的效果。

用法:

require("<模块名>")
require "<模块名>"

两种都可以。

查看数据类型:
三 SPU、SKU、Lua、OpenResty_第4张图片

2.4.8 表

三 SPU、SKU、Lua、OpenResty_第5张图片
定义数组并且赋值、取值:
三 SPU、SKU、Lua、OpenResty_第6张图片
把table内存释放掉——nil
三 SPU、SKU、Lua、OpenResty_第7张图片

2.4.9 模块

相当于java里的工具类
三 SPU、SKU、Lua、OpenResty_第8张图片
三 SPU、SKU、Lua、OpenResty_第9张图片

三 OpenResty

3.1 OpenResty介绍

OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台,由中国人章亦春发起,提供了很多高质量的第三方模块。

OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。

360,UPYUN,阿里云,新浪,腾讯网,去哪儿网,酷狗音乐等都是 OpenResty 的深度用户。

OpenResty 简单理解,就相当于封装了nginx,并且集成了LUA脚本,开发人员只需要简单的其提供了模块就可以实现相关的逻辑,而不再像之前,还需要在nginx中自己编写lua的脚本,再进行调用了。

3.2 OpenResty安装

linux安装openresty:

1.添加仓库执行命令

 yum install yum-utils
 yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

2.执行安装

yum install openresty

3.安装成功后 会在默认的目录如下:

/usr/local/openresty

安装nginx
安装完OpenResty后默认已经安装好了nginx,在目录:/usr/local/openresty/nginx 下。

修改/usr/local/openresty/nginx/conf/nginx.conf ,将配置文件使用的根设置为root,目的就是将来要使用lua脚本的时候 ,直接可以加载在root下的lua脚本。

#user nobody; 配置文件第一行原来为这样, 现改为下面的配置
user root root;

测试访问 http://192.168.200.128
三 SPU、SKU、Lua、OpenResty_第10张图片

你可能感兴趣的:(笔记)