文章目录

  • 1. 商品规格
    • 1.1 SPU 和 SKU
    • 1.2 分析商品规格的关系
    • 1.3 数据库设计
      • 1.3.1 商品规格组表
      • 1.3.2 商品规格参数表
  • 2. 商品规格组
    • 2.1 商品规格组前端
    • 2.2 实现商品规格组查询
      • 2.2.1 实体类
      • 2.2.2 Mapper
      • 2.2.3 Service
      • 2.2.4 Controller
      • 2.2.5 测试
  • 3. 商品规格参数
    • 3.1 商品规格参数前端
    • 3.2 实现商品规格参数查询
      • 3.2.1 Controller
      • 3.2.2 Service
      • 3.2.3 测试
  • 4. 商品
    • 4.1 分析商品的关系
    • 4.2 数据库设计
      • 4.2.1 SPU 表
      • 4.2.2 SKU 表
    • 4.3 商品前端
    • 4.4 实现商品查询
      • 4.4.1 实体类
      • 4.4.2 Mapper
      • 4.4.3 Controller
      • 4.4.4 Service
      • 4.4.5 测试

1. 商品规格

乐优商城是一个全品类的电商网站,因此商品的种类繁多,每一件商品,其属性又有差别。为了更准确描述商品及细分差别,抽象出两个概念:SPU 和 SKU

1.1 SPU 和 SKU

  • SPU:Standard Product Unit (标准产品单位) ,一组具有共同属性的商品集

  • SKU:Stock Keeping Unit(库存量单位),SPU 商品集因具体特性不同而细分的每个商品

上面的概念有些抽象,为便于理解下面有一张京东的 “小米 10” 商品页面图片:

  • 在页面中的 “小米 10” 就是一个商品集,即 SPU

  • 因为选择不同的颜色、版本而细分出不同的 “小米 10”,即 SKU。

    比如:钛银色、8GB+256GB 是一个 SKU;冰蓝色、8GB+128GB 是一个 SKU

两者的作用:

  • SPU 是一个抽象的商品集概念,是为了方便后台的管理。
  • SKU 才是具体要销售的商品,每一个 SKU 的价格、库存可能会不一样,用户购买的是 SKU 而不是 SPU。

1.2 分析商品规格的关系

我们看看京东的 “小米 10” 商品的规格页面:

可以很容易分析出这里有两张表:规格组和规格参数。并且一个规格组对应着多个规格参数,一个规格参数对应着一个规格组。规格组和规格参数之间是一对多的关系

并且一个分类对应着多个规格组,一个规格组对应着一个分类。分类和规格组之间是一对多的关系

再来看看京东搜索 “手机” 后的过滤条件:

可以分析出:我们需要直接根据 “手机” 分类,得出 “品牌” 规格参数等。并且一个分类对应着多个规格参数,一个规格参数对应着一个分类。分类和规格参数之间是一对多的关系

分类、规格组、规格参数之间的关系如下图所示:

1.3 数据库设计

1.3.1 商品规格组表

规格组表 tb_spec_group

CREATE TABLE `tb_spec_group` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`cid` bigint(20) NOT NULL COMMENT '商品分类id,一个分类下有多个规格组',`name` varchar(32) NOT NULL COMMENT '规格组的名称',PRIMARY KEY (`id`),KEY `key_category` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8 COMMENT='规格参数的分组表,每个商品分类下有多个规格参数组';

1.3.2 商品规格参数表

规格参数表 tb_spec_param

CREATE TABLE `tb_spec_param` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',`cid` bigint(20) NOT NULL COMMENT '商品分类id',`group_id` bigint(20) NOT NULL,`name` varchar(256) NOT NULL COMMENT '参数名',`numeric` tinyint(1) NOT NULL COMMENT '是否是数字类型参数,true或false',`unit` varchar(256) DEFAULT '' COMMENT '数字类型参数的单位,非数字类型可以为空',`generic` tinyint(1) NOT NULL COMMENT '是否是sku通用属性,true或false',`searching` tinyint(1) NOT NULL COMMENT '是否用于搜索过滤,true或false',`segments` varchar(1024) DEFAULT '' COMMENT '数值类型参数,如果需要搜索,则添加分段间隔值,如CPU频率间隔:0.5-1.0',PRIMARY KEY (`id`),KEY `key_group` (`group_id`),KEY `key_category` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8 COMMENT='规格参数组下的参数名';

这里有几个字段比较特殊,下面给出具体的解释:

  • numeric:用来判断规格参数是否是数字类型参数。如果是数字类型参数,还需要填写数字类型参数的单位。
  • generic:用来判断规格参数是否是 SKU 通用属性。比如上面的 “小米 10” 的 “颜色” 和 “版本” 这两个规格参数就不是 SKU 通用属性,而是 SKU 特有属性,所以它们的值为 false。
  • searching:用来判断规格参数是否用于搜索过滤。上面我们已经可以知道有些规格参数会作为搜索过滤的条件。
  • segments:分段间隔值。如果一个字段既是数字类型参数,还能用于搜索过滤,那就可以给他分几个间隔值,比如电池容量:0-2000mAh、2000mAh-3000mAh、3000mAh-4000mAh。

2. 商品规格组

2.1 商品规格组前端

我们打开规格参数的页面,可以看到左侧展示了商品的分类

点击一个分类的最终分类,可以看到右侧提示 “该分类下暂无规格组或尚未选择分类”,由此可以得知右侧是用来展示规格组数据的,只是现在暂时没有数据。

我们找到前端请求规格组数据的代码:

由此可以得知:

  • 请求方式:GET
  • 请求路径:/spec/groups
  • 请求参数:分类 id,这里用的是 Rest 风格的占位符
  • 返回参数:规格组的集合

2.2 实现商品规格组查询

2.2.1 实体类

在 leyou-item-interface 项目中添加两个实体类

规格组 SpecGroup

@Table(name = "tb_spec_group")
public class SpecGroup {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private Long cid;private String name;@Transientprivate List<SpecParam> params;// getter、setter、toString 方法省略
}

注意:这里的 params 属性并不与数据库字段相对应,所以加上了 @Transient

规格参数 SpecParam

@Table(name = "tb_spec_param")
public class SpecParam {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private Long cid;private Long groupId;private String name;@Column(name = "`numeric`")private Boolean numeric;private String unit;private Boolean generic;private Boolean searching;private String segments;// getter、setter、toString 方法省略
}

注意:这里的 numeric 属性在 MySQL 中是一个关键字,所以使用 @Column 表示它是一个字段

2.2.2 Mapper

在 leyou-item-service 项目中添加两个 Mapper

规格组 SpecGroupMapper

public interface SpecGroupMapper extends Mapper<SpecGroup> {}

规格参数 SpecParamMapper

public interface SpecParamMapper extends Mapper<SpecParam> {}

2.2.3 Service

在 leyou-item-service 项目中添加 Service

@Service
public class SpecificationService {@Autowiredprivate SpecGroupMapper specGroupMapper;@Autowiredprivate SpecParamMapper specParamMapper;/*** 根据分类 id 查询分组** @param cid* @return*/public List<SpecGroup> querySpecGroupsByCid(Long cid) {SpecGroup specGroup = new SpecGroup();specGroup.setCid(cid);List<SpecGroup> specGroups = specGroupMapper.select(specGroup);return specGroups;}
}

2.2.4 Controller

在 leyou-item-service 项目中添加 Controller

@RestController
@RequestMapping("/spec")
public class SpecificationController {@Autowiredprivate SpecificationService specificationService;/*** 根据分类 id 查询分组** @param cid* @return*/@GetMapping("/groups/{cid}")public ResponseEntity<List<SpecGroup>> querySpecGroupsByCid(@PathVariable("cid") Long cid) {List<SpecGroup> specGroups = specificationService.querySpecGroupsByCid(cid);if (CollectionUtils.isEmpty(specGroups)) {return ResponseEntity.notFound().build();}return ResponseEntity.ok(specGroups);}
}

2.2.5 测试

成功加载规格组数据

3. 商品规格参数

3.1 商品规格参数前端

点击一个规格组 “主体”

可以看到规格组的表格切换到了规格参数的表格,只是暂时还没有数据

我们找到前端请求规格参数数据的代码:

由此可以得知:

  • 请求方式:GET
  • 请求路径:/spec/params
  • 请求参数:规格组 id
  • 返回参数:规格参数的集合

3.2 实现商品规格参数查询

3.2.1 Controller

在 SpecificationController 中添加方法

/*** 根据条件查询规格参数** @param gid* @return*/
@GetMapping("/params")
public ResponseEntity<List<SpecParam>> querySpecParams(@RequestParam("gid") Long gid) {List<SpecParam> params = specificationService.querySpecParams(gid);if (CollectionUtils.isEmpty(params)) {return ResponseEntity.notFound().build();}return ResponseEntity.ok(params);
}

3.2.2 Service

在 SpecificationService 中添加方法

/*** 根据条件查询规格参数* @param gid* @return*/
public List<SpecParam> querySpecParams(Long gid) {SpecParam specParam = new SpecParam();specParam.setGroupId(gid);List<SpecParam> params = specParamMapper.select(specParam);return params;
}

3.2.3 测试

成功加载规格参数数据

4. 商品

前面我们已经介绍了 SPU 和 SKU 的概念,了解了 SPU 是一个商品集,而 SKU 才是具体要销售的商品。所以商品必不可少的两张表就是 SPU 和 SKU,下面我们分析一下 SPU、SKU 和其他表之间的关系。

4.1 分析商品的关系

还是用上面举过的例子,“小米 10” 就是一个 SPU,它只对应 “小米” 这一个品牌,但小米品牌有多个 SPU,如:小米 9、小米 8 等。品牌和 SPU 之间是一对多的关系

而 “小米 10” 是一部手机 ,它只对应手机这一个分类,而手机分类却可以对应多个 SPU。分类和 SPU 之间是一对多的关系

前面已经讲过了,一个 SPU 可以有多个 SKU,而一个 SKU 只能有一个 SPU。SPU 和 SKU 之间是一对多的关系

商品的关系如下图所示:

4.2 数据库设计

4.2.1 SPU 表

SPU 表 tb_spu

CREATE TABLE `tb_spu` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'spu id',`title` varchar(128) NOT NULL DEFAULT '' COMMENT '标题',`sub_title` varchar(256) DEFAULT '' COMMENT '子标题',`cid1` bigint(20) NOT NULL COMMENT '1级类目id',`cid2` bigint(20) NOT NULL COMMENT '2级类目id',`cid3` bigint(20) NOT NULL COMMENT '3级类目id',`brand_id` bigint(20) NOT NULL COMMENT '商品所属品牌id',`saleable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否上架,0下架,1上架',`valid` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0已删除,1有效',`create_time` datetime DEFAULT NULL COMMENT '添加时间',`last_update_time` datetime DEFAULT NULL COMMENT '最后修改时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=195 DEFAULT CHARSET=utf8 COMMENT='spu表,该表描述的是一个抽象性的商品,比如 iphone8';

这张表似乎少了一些字段,比如商品描述,售后信息等,但这些数据都比较大,为了不影响查询效率我们做了表的垂直拆分,将 SPU 的详情放到了另一张表 tb_spu_detail

CREATE TABLE `tb_spu_detail` (`spu_id` bigint(20) NOT NULL,`description` text COMMENT '商品描述信息',`generic_spec` varchar(2048) NOT NULL DEFAULT '' COMMENT '通用规格参数数据',`special_spec` varchar(1024) NOT NULL COMMENT '特有规格参数及可选值信息,json格式',`packing_list` varchar(1024) DEFAULT '' COMMENT '包装清单',`after_service` varchar(1024) DEFAULT '' COMMENT '售后服务',PRIMARY KEY (`spu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这里有几个字段比较特殊,下面给出具体的解释:

generic_spec

用来保存通用规格参数信息的值,这里为了方便查询,使用了 JSON 格式。

其中都是键值对:

  • key:对应的规格参数的 spec_param 的 id
  • value:对应规格参数的值

special_spec

用来保存特有规格参数及可选值,也就是 SKU 的特有属性。

其中都是键值对:

  • key:对应的规格参数的 spec_param 的 id
  • value:对应规格参数的数组,因为 SKU 特有属性可能有多个

4.2.2 SKU 表

SKU 表 tb_sku

CREATE TABLE `tb_sku` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'sku id',`spu_id` bigint(20) NOT NULL COMMENT 'spu id',`title` varchar(256) NOT NULL COMMENT '商品标题',`images` varchar(1024) DEFAULT '' COMMENT '商品的图片,多个图片以‘,’分割',`price` bigint(15) NOT NULL DEFAULT '0' COMMENT '销售价格,单位为分',`indexes` varchar(32) DEFAULT '' COMMENT '特有规格属性在spu属性模板中的对应下标组合',`own_spec` varchar(1024) DEFAULT '' COMMENT 'sku的特有规格参数键值对,json格式,反序列化时请使用linkedHashMap,保证有序',`enable` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否有效,0无效,1有效',`create_time` datetime NOT NULL COMMENT '添加时间',`last_update_time` datetime NOT NULL COMMENT '最后修改时间',PRIMARY KEY (`id`),KEY `key_spu_id` (`spu_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=27359021729 DEFAULT CHARSET=utf8 COMMENT='sku表,该表表示具体的商品实体,如黑色的 64g的iphone 8';

这里有几个字段比较特殊,下面给出具体的解释:

indexes

tb_spu_detail 表的 special_spec 字段是用来保存 SKU 特有属性的,而 indexes 字段就是这些特有属性的下标组合。这个设计在商品详情页会特别有用,当用户点击选中一个特有属性,你就能根据角标快速定位到 SKU。

比如 special_spec 字段如下:

indexes 字段:

  • 0_0_0:表示白色、3GB、16GB
  • 1_0_0:表示金色、3GB、16GB
  • 2_0_0:表示玫瑰金、3GB、16GB

own_spec

用来保存 SKU 特有属性的键值对,使用了 JSON 格式,比如:

SKU 还应该有一个库存字段,但 SKU 表中的其他字段读的频率较高,而库存字段写的频率比较高,因此做了表的垂直拆分,使读写不会互相干扰。

库存表 tb_stock

CREATE TABLE `tb_stock` (`sku_id` bigint(20) NOT NULL COMMENT '库存对应的商品sku id',`seckill_stock` int(9) DEFAULT '0' COMMENT '可秒杀库存',`seckill_total` int(9) DEFAULT '0' COMMENT '秒杀总数量',`stock` int(9) NOT NULL COMMENT '库存数量',PRIMARY KEY (`sku_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='库存表,代表库存,秒杀库存等信息';

4.3 商品前端

点击商品列表,可以看到这是一个可以实现分页、查询的表单,和之前做过的品牌的查询很相似。

我们找到前端请求商品数据的代码:


由此可以得知:

  • 请求方式:GET
  • 请求路径:spu/page
  • 请求参数:
    • key:搜索条件,String
    • saleable:上下架,boolean(全部为 null,上架为 true,下架为 false)
    • page:当前页,int
    • rows:每页大小,int
  • 返回参数:规格组的集合
    • total:总条数
    • items:当前页数据

4.4 实现商品查询

4.4.1 实体类

在 leyou-item-interface 中添加实体类:

SPU

@Table(name = "tb_spu")
public class Spu {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private Long brandId;private Long cid1;// 1级类目private Long cid2;// 2级类目private Long cid3;// 3级类目private String title;// 标题private String subTitle;// 子标题private Boolean saleable;// 是否上架private Boolean valid;// 是否有效,逻辑删除用private Date createTime;// 创建时间private Date lastUpdateTime;// 最后修改时间// getter、setter、toString 方法省略
}

SPU 详情

@Table(name="tb_spu_detail")
public class SpuDetail {@Idprivate Long spuId;// 对应的SPU的idprivate String description;// 商品描述private String specialSpec;// 商品特殊规格的名称及可选值模板private String genericSpec;// 商品的全局规格属性private String packingList;// 包装清单private String afterService;// 售后服务// getter、setter、toString 方法省略
}

此时,我们发现一个问题,商品页面中的商品分类和品牌的应该是字符串

SPU 表的商品分类和品牌却只是 id,所以在实体类中还需要有两个属性,用来封装商品分类的 name 和品牌分类的 name。我们肯定不能直接修改 Spu 实体类,但可以拓展一个实体类 SpuBo,Bo 即 Business Object

public class SpuBo extends Spu{private String cname;private String bname;// getter、setter、toString 方法省略
}

4.4.2 Mapper

在 leyou-item-service 项目中添加两个 Mapper

Spu

public interface SpuMapper extends Mapper<Spu> {}

Spu 详情

public interface SpuDetail extends Mapper<SpuDetail> {}

4.4.3 Controller

在 leyou-item-service 项目中添加 Controller

@RestController
@RequestMapping("/spu")
public class SpuController {@Autowiredprivate SpuService spuService;/*** 根据查询条件分页查询商品信息* @param key 搜索条件* @param saleable 上下架* @param page 当前页* @param rows 每页大小* @return*/@GetMapping("/page")public ResponseEntity<PageResult<SpuBo>> querySpuByPage(@RequestParam(name = "key", required = false) String key,@RequestParam(name = "saleable", required = false) Boolean saleable,@RequestParam(name = "page", defaultValue = "1") Integer page,@RequestParam(name = "rows", defaultValue = "5") Integer rows) {PageResult<SpuBo> pageResult = spuService.querySpuByPage(key, saleable, page, rows);if (CollectionUtils.isEmpty(pageResult.getItems())) {ResponseEntity.notFound().build();}return ResponseEntity.ok(pageResult);}
}

4.4.4 Service

在 leyou-item-service 项目中添加 Service

@Service
public class SpuService {@Autowiredprivate SpuMapper spuMapper;@Autowiredprivate BrandMapper brandMapper;@Autowiredprivate CategoryService categoryService;/*** 根据查询条件分页查询商品信息** @param key      搜索条件* @param saleable 上下架* @param page     当前页* @param rows     每页大小* @return*/public PageResult<SpuBo> querySpuByPage(String key, Boolean saleable, Integer page, Integer rows) {// 初始化 example 对象Example example = new Example(Spu.class);Example.Criteria criteria = example.createCriteria();// 添加搜索条件if (StringUtils.isNotBlank(key)) {criteria.andLike("title", "%" + key + "%");}// 添加上下架if (saleable != null) {criteria.andEqualTo("saleable", saleable);}// 添加分页PageHelper.startPage(page, rows);// 执行查询,获取 Spu 集合List<Spu> spus = spuMapper.selectByExample(example);// 将 Spu 集合包装成 pageInfoPageInfo<Spu> spuPageInfo = new PageInfo<>(spus);// 将 Spu 集合转化为 SpuBo 集合ArrayList<SpuBo> spuBos = new ArrayList<>();for (Spu spu : spus) {SpuBo spuBo = new SpuBo();// 复制共同的属性到 SpuBo 对象中BeanUtils.copyProperties(spu, spuBo);// 查询分类名称,并添加到 SpuBo 对象中List<String> names = categoryService.queryNamesByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));spuBo.setCname(StringUtils.join(names,"/"));// 查询品牌名称,并添加到 SpuBo 对象中Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());spuBo.setBname(brand.getName());// 添加 SpuBo 到 SpuBo 集合spuBos.add(spuBo);}// 返回 PageResult<SpuBo>return new PageResult<SpuBo>(spuPageInfo.getTotal(), spuBos);}
}

在 CategoryService 添加方法

/*** 查询分类名称* @param ids* @return*/
public List<String> queryNamesByIds(List<Long> ids) {ArrayList<String> names = new ArrayList<>();for (Long id : ids) {Category category = categoryMapper.selectByPrimaryKey(id);names.add(category.getName());}return names;
}

4.4.5 测试

乐优商城(四)商品规格管理相关推荐

  1. 乐优商城day13(商品详情页,rabbitMQ安装)

    所有代码发布在 [https://github.com/hades0525/leyou] Day13(rabbitmq) 2019年2月13日 14:45 使用thymeleaf thymeleaf基 ...

  2. 乐优商城学习笔记五-商品规格管理

    0.学习目标 了解商品规格数据结构设计思路 实现商品规格查询 了解SPU和SKU数据结构设计思路 实现商品查询 了解商品新增的页面实现 独立编写商品新增后台功能 1.商品规格数据结构 乐优商城是一个全 ...

  3. 【javaWeb微服务架构项目——乐优商城day05】——商品规格参数管理(增、删、改,查已完成),SPU和SKU数据结构,商品查询

    乐优商城day05 0.学习目标 1.商品规格数据结构 1.1.SPU和SKU 1.2.数据库设计分析 1.2.1.思考并发现问题 1.2.2.分析规格参数 1.2.3.SKU的特有属性 1.2.4. ...

  4. 乐优商城(05)--商品管理

    乐优商城(05)–商品管理 一.导入图片资源 现在商品表中虽然有数据,但是所有的图片信息都是无法访问的,因此需要把图片导入到服务器中: 将images.zip文件上传至/leyou/static目录: ...

  5. 乐优商城之项目搭建(四)

    文章目录 (一)项目分类 (二)电商行业 (三)专业术语 (四)项目介绍 (五)技术选型 (六)开发环境 (七)搭建后台环境:父工程 (八)搭建后台环境:eureka (九)搭建后台环境:zuul ( ...

  6. 商城-商品规格管理-商品规格数据结构

    商城-商品规格管理-商品规格数据结构 1.商品规格数据结构 1.1.SPU和SKU 1.2.数据库设计分析 1.2.1.思考并发现问题 1.2.2.分析规格参数 1.2.3.SKU的特有属性 1.2. ...

  7. 【javaWeb微服务架构项目——乐优商城day03】——(搭建后台管理前端,Vuetify框架,使用域名访问本地项目,实现商品分类查询,cors解决跨域,品牌的查询)

    乐优商城day03 0.学习目标 1.搭建后台管理前端 1.1.导入已有资源 1.2.安装依赖 1.3.运行一下看看 1.4.目录结构 1.5.调用关系 2.Vuetify框架 2.1.为什么要学习U ...

  8. 乐优商城笔记六:商品详情页

    使用模板引擎 Thymeleaf + nginx 完成商品详情页静态化 完成乐优商城商品详情页 搭建商品详情页微服务 创建子工程 GroupId:com.leyou.service ArtifactI ...

  9. 乐优商城 Day 09(thymeleaf,Rabbitmq,商品详情页,非教程)

    乐优商城学习Day09: 注意:此次代码都是在第八天的基础上 第八天的链接如下: https://blog.csdn.net/zcylxzyh/article/details/100859210 此次 ...

最新文章

  1. Photoshop 混色模式学习
  2. 算法竞赛入门经典读书笔记(二)7.1简单枚举
  3. 【正一专栏】梅西、内马尔分开明天会更好
  4. 用神经网络分类随机数与无理数
  5. 局部特征(2)——Harris角点
  6. winform在表格中输入一个完整的时间字段_B端交互组件之表格篇
  7. css margin和border,Margin、Border、Padding属性的区别和联系
  8. 留言板小程序开发笔记3
  9. sumk-db的主要方法及注解
  10. 搬家请搬家公司好还是请朋友帮忙好?
  11. 源码多多- Discuz x2.5 版块的常用设置方法和技巧
  12. mac osx终端命令大全
  13. win10taskkill强行结束进程_win10系统强制结束进程命令的方案
  14. css字体加粗_CSS字体
  15. 心はちょっと疲れた、誰も片隅に休んで……作者の宝物は
  16. 完美解决:Java微信语音amr格式转mp3格式,兼容Linux/Mac/Windows,支持Maven
  17. 基金定投:100%抄到底的方法
  18. Android 原生分享文件到微信
  19. SpringBoot 和 Vue 前后端分离教程(附源码)
  20. linux同时开启两个端口,linux下squid开多个端口的办法

热门文章

  1. Day2--正则表达式
  2. idea全局搜索文件
  3. 面试:计算机网络基础详解(一)
  4. 搞定计算机网络面试,看这篇就够了
  5. 图像的形态学处理总结
  6. 云宏CTO张国强:云宏超融合大数据一体机,中国云数一体化神器!
  7. 重构ElementUI解决DatePicker日期选择组件修改父组件placement参数问题[Vue.js项目实践: 新冠自检系统]
  8. 【应用层】DNS协议
  9. bton框架业务核心流程架构
  10. 多传感器融合标定方法汇总