1. 关于此项目

此项目是一个自营性质电商类型的项目。

当前目标是设计后台管理相关功能。

2. 关于项目的开发流程

开发项目的标准流程应该有:需求分析、可行性分析、总体设计、详细设计等。

建议课后学习《软件工程》。

在具体开发时,应该先创建数据库、数据表,然后创建项目进行开发。

3. 创建数据库与数据表

创建mall_pms数据库:

CREATE DATABASE mall_pms;

在此数据库中创建数据表:

-- 数据库:mall_pms

-- 相册表:创建数据表
drop table if exists pms_album;
create table pms_album
(
id bigint unsigned auto_increment comment '记录id',
name varchar(50) default null comment '相册名称',
description varchar(255) default null comment '相册简介',
sort tinyint unsigned default 0 comment '自定义排序序号',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '相册' charset utf8mb4; -- 相册表:为相册名称字段添加索引
create index idx_album_name on pms_album (name); -- 图片表:创建数据表
drop table if exists pms_picture;
create table pms_picture
(
id bigint unsigned auto_increment comment '记录id',
album_id bigint unsigned default null comment '相册id',
url varchar(255) default null comment '图片url',
description varchar(255) default null comment '图片简介',
width smallint unsigned default null comment '图片宽度,单位:px',
height smallint unsigned default null comment '图片高度,单位:px',
is_cover tinyint unsigned default 0 comment '是否为封面图片,1=是,0=否',
sort tinyint unsigned default 0 comment '自定义排序序号',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '图片' charset utf8mb4; -- 品牌表:创建数据表
drop table if exists pms_brand;
create table pms_brand
(
id bigint unsigned auto_increment comment '记录id',
name varchar(50) default null comment '品牌名称',
pinyin varchar(50) default null comment '品牌名称的拼音',
logo varchar(255) default null comment '品牌logo的URL',
description varchar(255) default null comment '品牌简介',
keywords varchar(255) default null comment '关键词列表,各关键词使用英文的逗号分隔',
sort tinyint unsigned default 0 comment '自定义排序序号',
sales int unsigned default 0 comment '销量(冗余)',
product_count int unsigned default 0 comment '商品种类数量总和(冗余)',
comment_count int unsigned default 0 comment '买家评论数量总和(冗余)',
positive_comment_count int unsigned default 0 comment '买家好评数量总和(冗余)',
enable tinyint unsigned default 0 comment '是否启用,1=启用,0=未启用',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '品牌' charset utf8mb4; -- 品牌表:为品牌名称字段添加索引
create index idx_brand_name on pms_brand (name); -- 类别表:创建数据表
drop table if exists pms_category;
create table pms_category
(
id bigint unsigned auto_increment comment '记录id',
name varchar(50) default null comment '类别名称',
parent_id bigint unsigned default 0 comment '父级类别id,如果无父级,则为0',
depth tinyint unsigned default 1 comment '深度,最顶级类别的深度为1,次级为2,以此类推',
keywords varchar(255) default null comment '关键词列表,各关键词使用英文的逗号分隔',
sort tinyint unsigned default 0 comment '自定义排序序号',
icon varchar(255) default null comment '图标图片的URL',
enable tinyint unsigned default 0 comment '是否启用,1=启用,0=未启用',
is_parent tinyint unsigned default 0 comment '是否为父级(是否包含子级),1=是父级,0=不是父级',
is_display tinyint unsigned default 0 comment '是否显示在导航栏中,1=启用,0=未启用',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '类别' charset utf8mb4; -- 类别表:为类别名称字段添加索引
create index idx_category_name on pms_category (name); -- 品牌类别关联表:创建数据表
drop table if exists pms_brand_category;
create table pms_brand_category
(
id bigint unsigned auto_increment comment '记录id',
brand_id bigint unsigned default null comment '品牌id',
category_id bigint unsigned default null comment '类别id',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '品牌与类别关联' charset utf8mb4; -- 属性表:创建数据表
drop table if exists pms_attribute;
create table pms_attribute
(
id bigint unsigned auto_increment comment '记录id',
template_id bigint unsigned default null comment '所属属性模版id',
name varchar(50) default null comment '属性名称',
description varchar(255) default null comment '简介(某些属性名称可能相同,通过简介补充描述)',
type tinyint unsigned default 0 comment '属性类型,1=销售属性,0=非销售属性',
input_type tinyint unsigned default 0 comment '输入类型,0=手动录入,1=单选,2=多选,3=单选(下拉列表),4=多选(下拉列表)',
value_list varchar(255) default null comment '备选值列表',
unit varchar(50) default null comment '计量单位',
sort tinyint unsigned default 0 comment '自定义排序序号',
is_allow_customize tinyint unsigned default 0 comment '是否允许自定义,1=允许,0=禁止',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '属性' charset utf8mb4; -- 属性模版表:创建数据表
drop table if exists pms_attribute_template;
create table pms_attribute_template
(
id bigint unsigned auto_increment comment '记录id',
name varchar(50) default null comment '属性模版名称',
pinyin varchar(50) default null comment '属性模版名称的拼音',
keywords varchar(255) default null comment '关键词列表,各关键词使用英文的逗号分隔',
sort tinyint unsigned default 0 comment '自定义排序序号',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '属性模版' charset utf8mb4; -- 属性模版表:为属性模版名称字段添加索引
create index idx_attribute_template_name on pms_attribute_template (name); -- 类别与属性模版关联表:创建数据表
drop table if exists pms_category_attribute_template;
create table pms_category_attribute_template
(
id bigint unsigned auto_increment comment '记录id',
category_id bigint unsigned default null comment '类别id',
attribute_template_id bigint unsigned default null comment '属性模版id',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment '类别与属性模版关联' charset utf8mb4; -- SPU(Standard Product Unit)表:创建数据表
drop table if exists pms_spu;
create table pms_spu
(
id bigint unsigned not null comment '记录id',
name varchar(50) default null comment 'SPU名称',
type_number varchar(50) default null comment 'SPU编号',
title varchar(255) default null comment '标题',
description varchar(255) default null comment '简介',
list_price decimal(10, 2) default null comment '价格(显示在列表中)',
stock int unsigned default 0 comment '当前库存(冗余)',
stock_threshold int unsigned default 0 comment '库存预警阈值(冗余)',
unit varchar(50) default null comment '计件单位',
brand_id bigint unsigned default null comment '品牌id',
brand_name varchar(50) default null comment '品牌名称(冗余)',
category_id bigint unsigned default null comment '类别id',
category_name varchar(50) default null comment '类别名称(冗余)',
attribute_template_id bigint unsigned default null comment '属性模版id',
album_id bigint unsigned default null comment '相册id',
pictures varchar(500) default null comment '组图URLs,使用JSON数组表示',
keywords varchar(255) default null comment '关键词列表,各关键词使用英文的逗号分隔',
tags varchar(255) default null comment '标签列表,各标签使用英文的逗号分隔,原则上最多3个',
sales int unsigned default 0 comment '销量(冗余)',
comment_count int unsigned default 0 comment '买家评论数量总和(冗余)',
positive_comment_count int unsigned default 0 comment '买家好评数量总和(冗余)',
sort tinyint unsigned default 0 comment '自定义排序序号',
is_deleted tinyint unsigned default 0 comment '是否标记为删除,1=已删除,0=未删除',
is_published tinyint unsigned default 0 comment '是否上架(发布),1=已上架,0=未上架(下架)',
is_new_arrival tinyint unsigned default 0 comment '是否新品,1=新品,0=非新品',
is_recommend tinyint unsigned default 0 comment '是否推荐,1=推荐,0=不推荐',
is_checked tinyint unsigned default 0 comment '是否已审核,1=已审核,0=未审核',
check_user varchar(50) default null comment '审核人(冗余)',
gmt_check datetime default null comment '审核通过时间(冗余)',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment 'SPU(Standard Product Unit)' charset utf8mb4; -- SPU详情表:创建数据表
drop table if exists pms_spu_detail;
create table pms_spu_detail
(
id bigint unsigned auto_increment comment '记录id',
spu_id bigint unsigned default null comment 'SPU id',
detail text default null comment 'SPU详情,应该使用HTML富文本,通常内容是若干张图片',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment 'SPU详情' charset utf8mb4; -- SKU(Stock Keeping Unit)表:创建数据表
drop table if exists pms_sku;
create table pms_sku
(
id bigint unsigned not null comment '记录id',
spu_id bigint unsigned default null comment 'SPU id',
title varchar(255) default null comment '标题',
bar_code varchar(255) default null comment '条型码',
attribute_template_id bigint unsigned default null comment '属性模版id',
specifications varchar(2500) default null comment '全部属性,使用JSON格式表示(冗余)',
album_id bigint unsigned default null comment '相册id',
pictures varchar(500) default null comment '组图URLs,使用JSON格式表示',
price decimal(10, 2) default null comment '单价',
stock int unsigned default 0 comment '当前库存',
stock_threshold int unsigned default 0 comment '库存预警阈值',
sales int unsigned default 0 comment '销量(冗余)',
comment_count int unsigned default 0 comment '买家评论数量总和(冗余)',
positive_comment_count int unsigned default 0 comment '买家好评数量总和(冗余)',
sort tinyint unsigned default 0 comment '自定义排序序号',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment 'SKU(Stock Keeping Unit)' charset utf8mb4; -- SKU规格参数表(存储各SKU的属性与值,即规格参数):创建数据表
drop table if exists pms_sku_specification;
create table pms_sku_specification
(
id bigint unsigned auto_increment comment '记录id',
sku_id bigint unsigned default null comment 'SKU id',
attribute_id bigint unsigned default null comment '属性id',
attribute_name varchar(50) default null comment '属性名称',
attribute_value varchar(50) default null comment '属性值',
unit varchar(10) default null comment '自动补充的计量单位',
sort tinyint unsigned default 0 comment '自定义排序序号',
gmt_create datetime default null comment '数据创建时间',
gmt_modified datetime default null comment '数据最后修改时间',
primary key (id)
) comment 'SKU数据' charset utf8mb4; -- -------------------------- --
-- 以下是插入测试数据及一些测试访问 --
-- -------------------------- -- -- 品牌表:插入测试数据
insert into pms_brand (name, pinyin, description, keywords, enable)
values ('华为', 'huawei', '华为专注网络设备三十年', '华为,huawei,mate,magicbook', 1),
('小米', 'xiaomi', '小米,为发烧而生', '小米,xiaomi,发烧', 1),
('苹果', 'pingguo', '苹果,全球知名品牌', '苹果,apple,pingguo,iphone,mac', 1); -- 类别表:插入测试数据
insert into pms_category (name, parent_id, depth, is_parent, keywords, enable, is_display)
values ('手机 / 运营商 / 数码', 0, 1, 1, null, 1, 1),
('手机通讯', 1, 2, 1, '手机,电话', 1, 1),
('智能手机', 2, 3, 0, null, 1, 1),
('非智能手机', 2, 3, 0, null, 1, 1),
('电脑 / 办公', 0, 1, 1, null, 1, 1),
('电脑整机', 5, 2, 1, '电脑,计算机,微机,服务器,工作站', 1, 1),
('电脑配件', 5, 2, 1, '配件,组装,CPU,内存,硬盘', 1, 1),
('笔记本', 6, 3, 0, '电脑,笔记本,微机,便携', 1, 1),
('台式机 / 一体机', 6, 3, 0, '台式机,一体机', 1, 1); -- 品牌类别表:插入测试数据
insert into pms_brand_category (brand_id, category_id)
values (1, 3),
(2, 3),
(3, 3),
(1, 8),
(2, 8),
(3, 8),
(1, 9),
(3, 9); -- 关联测试查询:各品牌有哪些类别的产品
select pms_brand_category.id, pms_brand.name, pms_category.name
from pms_brand_category
left join pms_brand
on pms_brand_category.brand_id = pms_brand.id
left join pms_category
on pms_brand_category.category_id = pms_category.id
order by pms_brand.pinyin; -- 属性表:插入测试数据
insert into pms_attribute (name, description, type, input_type, value_list, unit, is_allow_customize)
values ('屏幕尺寸', '智能手机屏幕尺寸', 0, 1, '6.1,6.3', '英寸', 1),
('屏幕尺寸', '笔记本电脑屏幕尺寸', 0, 1, '14,15', '英寸', 1),
('颜色', '智能手机颜色', 0, 1, '黑色,金色,白色', null, 1),
('颜色', '衬衣颜色', 0, 1, '白色,蓝色,灰色,黑色', null, 1),
('运行内存', '智能手机运行内存', 0, 1, '4,8,16', 'GB', 1),
('CPU型号', '智能手机CPU型号', 0, 1, '骁龙870,骁龙880', null, 1),
('机身毛重', '智能手机机身毛重', 0, 0, null, 'g', 0),
('机身存储', '智能手机机身存储', 0, 1, '64,128,256,512', 'GB', 0),
('操作系统', '智能手机操作系统', 0, 1, 'Android,iOS', null, 0),
('操作系统', '电脑操作系统', 0, 1, '无,Windows 7,Windows 10,Ubuntu,Mac OS', null, 0); -- 属性模版表:插入测试数据
insert into pms_attribute_template (name, pinyin, keywords)
values ('智能手机', 'zhinengshouji', '手机'),
('服装-上身', 'fuzhuang', '服装,上衣'),
('服装-裤子', 'fuzhuang', '服装,裤'),
('笔记本电脑', 'bijibendiannao', '电脑,笔记本'),
('台式电脑', 'taishidiannao', '电脑,台式电脑,台式机'); -- 相册表:插入测试数据
insert into pms_album (name, description)
values ('iPhone 13', null),
('Mi 11 Ultra', null); -- 图片表:插入测试数据
insert into pms_picture (album_id, url, description, width, height)
values (1, '模拟数据:iPhone 13图片URL-1', null, 1024, 768),
(1, '模拟数据:iPhone 13图片URL-2', null, 1024, 768),
(1, '模拟数据:iPhone 13图片URL-3', null, 1024, 768),
(1, '模拟数据:iPhone 13图片URL-4', null, 1024, 768),
(1, '模拟数据:iPhone 13图片URL-5', null, 1024, 768),
(2, '模拟数据:Mi 11 Ultra图片URL-1', null, 1024, 768),
(2, '模拟数据:Mi 11 Ultra图片URL-2', null, 1024, 768),
(2, '模拟数据:Mi 11 Ultra图片URL-3', null, 1024, 768),
(2, '模拟数据:Mi 11 Ultra图片URL-4', null, 1024, 768),
(2, '模拟数据:Mi 11 Ultra图片URL-5', null, 1024, 768); -- SPU表:插入测试数据
insert into pms_spu (id, name, type_number, title, description, list_price, stock, stock_threshold, unit, brand_id,
brand_name, category_id, category_name, keywords, tags)
values (202112010000001, 'iPhone 13', 'A2404', '苹果手机iPhone 13(A2404)', '2021年新款,全网首发',
5199.99, 5000, 20, '部', 3, '苹果', 3, '智能手机', 'ip13,iPhone13,苹果13', '20w快充,NFC,无线充电'),
(202112010000002, '小米11 Ultra', 'M112021', '小米11 Ultra(M112021)', '2021年最新旗舰机',
5899.99, 8000, 20, '部', 2, '小米', 3, '智能手机', 'mi11,xiaomi11,ultra', '67w快充,1亿像素,5000毫安电池'); -- SPU详情表:插入测试数据
insert into pms_spu_detail (spu_id, detail)
values (1, '<div>iPhone 13的详情HTML</div>'),
(2, '<div>小米11 Ultra的详情HTML</div>'); -- SKU(Stock Keeping Unit)表:插入测试数据
insert into pms_sku (id, spu_id, title, attribute_template_id, specifications, price, stock, stock_threshold)
values (202112010000001, 2, '2021年新款,小米11 Ultra黑色512G,16G超大内存120Hz高刷67w快充', 1,
'{"attributes":[{"id":1,"name":"屏幕尺寸","value":"6.1寸"},{"id":3,"name":"颜色","value":"黑色"},{"id":5,"name":"运行内存","value":"16GB"}]}',
6999.99, 3000, 50),
(202112010000002, 2, '2021年新款,小米11 Ultra白色512G,8G超大内存120Hz高刷67w快充', 1,
'{"attributes":[{"id":1,"name":"屏幕尺寸","value":"6.1寸"},{"id":3,"name":"颜色","value":"白色"},{"id":5,"name":"运行内存","value":"8GB"}]}',
6499.99, 3000, 50); -- SKU规格参数表(存储各SKU的属性与值,即规格参数):插入测试数据
insert into pms_sku_specification (sku_id, attribute_id, attribute_name, attribute_value, unit)
values (1, 1, '屏幕尺寸', '6.1', '寸'),
(1, 3, '颜色', '黑色', null),
(1, 5, '运行内存', '16', 'GB'),
(2, 1, '屏幕尺寸', '6.1', '寸'),
(2, 3, '颜色', '白色', null),
(2, 5, '运行内存', '8', 'GB'); -- 查看数据表结构
desc pms_album;
desc pms_picture;
desc pms_category;
desc pms_brand;
desc pms_brand_category;
desc pms_attribute;
desc pms_attribute_template;
desc pms_spu;
desc pms_spu_detail;
desc pms_sku;
desc pms_sku_specification;

4. 关于Project与Module

Project:项目 / 工程

Module:模块

在较大规范的项目开发中,可能会把代码区分为多个Module进行开发,即某1个Project中可能有多个Module,各Module允许独立开发、独立运行,并且,可以在Project或某个父级Module中,对其子级的依赖项等部分的内容进行统筹管理。

需要注意:并不是每个Module都是可以独立运行的,在开发实践中,如果某些代码是多个Module都需要使用的,可以把这部分代码写在专门的Module中,其它Module依赖这个专门的Module即可(就像添加某个依赖项一样)。

当使用Project结合多个Module开发时,Project基本上不需要编写任何与功能相关的代码,只需要配置好pom.xml即可。

5. 创建Project

使用Spring Boot创建向导来创建Project,相关参数:

  • Spring Boot父工程版本:2.5.9
  • groupId:cn.tedu
  • artifactId:csmall-server
  • version:0.0.1-SNAPSHOT

由于Project并不需要运行(也不能运行),对于各依赖项,只需要管理即可,并不需要实际的添加!

在Project的pom.xml中,如果直接使用<dependencies>节点配置依赖项,则每个Module可以直接使用这些依赖项!但是,不推荐这样使用,因为Spring Boot的许多依赖都是支持自动配置的,如果在Module中自带了不需要使用的依赖项,反而容易导致错误,即使不会导致错误,也会因为自带了不需要使用的依赖项而导致最终的目标文件大。

通常,会将依赖项的代码放在<dependencyManagement>节点中,则在<dependencyManagement>之下的依赖项都不会默认出现在当前Project及各子级的Module中,其主要作用是配置各依赖项的版本,接下来,无论是在当前Project还是子级Module中,使用<dependencies>添加依赖项时,都可以不指定<version>节点来配置版本,默认使用的就是在<dependencyManagement>中配置的版本。

为了在当前pom.xml集中管理各依赖的版本号,推荐在<properties>中添加一些“变量”,用于配置版本号,在<dependencyManagement><dependencies>中添加依赖时,都可以引用此处的“变量”表示版本,例如:

<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.5.9</spring-boot.version>
<mybatis-boot.version>2.2.2</mybatis-boot.version>
<mysql.version>8.0.28</mysql.version>
<lombok.version>1.18.22</lombok.version>
</properties>

另外,由于Project并不实现的编写需要运行的功能代码,更不会直接编译打包或运行,所以,在Project的pom.xml中的<build>节点是不必要的!

最后,把Project的src全部删除!

6. 商品管理模块项目

应该在Project下创建某个Module,用于开发商品管理相关的功能,为了便于过渡到后续将要使用的微服务架构(需要将业务逻辑层的接口声明在专门的Module中,便于被其它微服务Module依赖),商品管理的Module需要再细分为2个,所以,目前项目结构应该是:

cgb2202-csmall-server[project]
csmall-product
csmall-product-webapi
csmall-product-service

当存在Project和Module的“父子关系”或后续可能存在Module与Module的“父子关系”时,应该在父级的pom.xml中添加:

<packaging>pom</packaging>

并且,在父级的pom.xml中,通过<modules>节点配置各子级Module,例如:

<modules>
<module>csmall-product</module>
</modules>

创建Module的操作步骤为:在cgb2202-csmall-server下创建csmall-product,再在csmall-product下创建csmall-product-webapi

当Project和各Module创建出来后,调整各pom.xml文件。

最终,cgb2202-csmall-server根级Project的pom.xml为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- Spring Boot父项目 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> <!-- 当前项目的信息 -->
<groupId>cn.tedu</groupId>
<artifactId>csmall-server</artifactId>
<version>0.0.1-SNAPSHOT</version> <!-- 聚合项目中的父级Project或父级Module都应该做以下配置 -->
<packaging>pom</packaging> <!-- 当前Project的各子级Module -->
<modules>
<module>csmall-product</module>
</modules> <!-- 属性配置,主要配置各依赖项的版本号对应的“变量” -->
<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.5.9</spring-boot.version>
<mybatis-boot.version>2.2.2</mybatis-boot.version>
<mysql.version>8.0.28</mysql.version>
<lombok.version>1.18.22</lombok.version>
<druid.version>1.1.20</druid.version>
</properties> <!-- 依赖管理,主要管理各依赖项的版本,使得子级Module添加依赖时不必指定版本 -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot Validation:验证请求参数的基本格式 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Web:支持Spring MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Mybatis Spring Boot:Mybatis及对Spring Boot的支持 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-boot.version}</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>${mysql.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>${lombok.version}</version>
</dependency>
<!-- Druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- Spring Boot Test:测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
</dependencyManagement> </project>

csmall-productpom.xml为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- 父级项目 -->
<parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent> <!-- 当前项目的信息 -->
<groupId>cn.tedu</groupId>
<artifactId>csmall-product</artifactId>
<version>0.0.1-SNAPSHOT</version> <!-- 聚合项目中的父级Project或父级Module都应该做以下配置 -->
<packaging>pom</packaging> <!-- 当前Project的各子级Module -->
<modules>
<module>csmall-product-webapi</module>
</modules> </project>

最后,在csmall-product-webapipom.xml为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <!-- 父级项目 -->
<parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall-product</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent> <!-- 当前项目的信息 -->
<groupId>cn.tedu</groupId>
<artifactId>csmall-product-webapi</artifactId>
<version>0.0.1-SNAPSHOT</version> <!-- 当前项目需要使用的依赖项 -->
<dependencies>
<!-- Spring Boot Validation:验证请求参数的基本格式 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Spring Boot Web:支持Spring MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Mybatis Spring Boot:Mybatis及对Spring Boot的支持 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!-- Spring Boot Test:测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </project>

7. 关于编写代码

根据已经添加的数据表,目前此项目中需要管理的数据类型大致有:

  • 品牌
  • 类别
  • 图片
  • 相册
  • 属性
  • 属性模版
  • SPU
  • SKU
  • 相关的关联表

首先,需要分析以上数据类型的开发先后顺序,部分数据之间存在依赖与被依赖关系,例如SKU肯定归属于某个SPU,在开发时,必须先开发SPU,再开发SKU,同理,必须先开发品牌,才可以开发SPU……

根据分析,必要的顺序为:(品牌 | 类别 | (相册 >>> 图片) | (属性模板 >>> 属性)) >>> SPU >>> SKU。

分析出必要顺序后,存在一些不需要严格区分顺序的数据类型,例如以上的品牌和类型,实际的开发顺序可以是先简单、后复杂,例如品牌数据通常比类别数据更加简单,则应该先开发品牌数据的管理,再开发类别数据的管理。

本次学习过程中,先开发类别,至于品牌,可自行课后完成!

当确定了需要处理类别的数据时,需要规划需要开发此数据的哪些管理功能,例如:添加类别、启用类别、禁用类别、修改类别的基本信息、根据id查询、根据parent_id查询列表……

以上管理类别数据的功能,开发顺序应该是:添加类别 >>> (根据id查询 | 根据parent_id查询列表) >>> (启用类别 | 禁用类别 | 修改类别的基本信息)

8. 类别管理--添加类别--持久层

8.1. 配置

由于目前是本项目第1次开发持久层,必须先完成必要的配置,包括:

  • 连接到数据库(配置连接数据库的参数)
  • 使用@MapperScan指定接口所在的包
  • 配置mybatis.mapper-locations指定XML文件的位置

应该先在csmall-product-webapisrc\main\resources下创建application-dev.properties文件,在其中添加连接数据库的参数:

# 连接数据库的配置信息
spring.datasource.url=jdbc:mysql://localhost:3306/mall_pms?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root

然后,在application.properties中添加配置:

# 激活Profile配置
spring.profiles.active=dev
# 连接数据库的固定配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # Mybatis的XML文件位置
mybatis.mapper-locations=classpath:mapper/*.xml

然后,需要在src/main/resources下自行创建mapper文件夹,与以上配置对应。

还需要自行创建配置类,用于配置Mapper接口文件所在的包,则在cn.tedu.csmall.product.webapi下创建mapper子包,并在cn.tedu.csmall.product.webapi下创建config.MybatisConfiguration配置类,进行配置:

package cn.tedu.csmall.product.webapi.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration; @Configuration
@MapperScan("cn.tedu.csmall.product.webapi.mapper")
public class MybatisConfiguration { }

完成后,可以尝试测试连接到数据库,则在src/test/java下找到默认即存在的测试类,编写并执行测试:

package cn.tedu.csmall.product.webapi;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import javax.sql.DataSource; @SpringBootTest
class CsmallProductWebapiApplicationTests { @Autowired
DataSource dataSource; @Test
void contextLoads() {
} @Test
void testConnection() {
Assertions.assertDoesNotThrow(() -> {
dataSource.getConnection();
});
} }

执行整个测试,应该能够通过测试。

8.2. 规划需要执行的SQL语句

此次需要执行的是“增加类别”,其数据操作的本质是向pms_category表中插入数据,需要执行的SQL语句大致是:

insert into pms_category (除了id以外的字段的列表) values (与字段列表匹配的各字段值);

具体表现为:

insert into pms_category (name, parent_id, depth, keywords, sort, icon, enable, is_parent, is_display, gmt_create, gmt_modified) values (值列表);

另外,还应该考虑在“添加类别”时,是否需要执行相关的检查,因为这些检查很可能是通过查询数据库来实现的,则在持久层也需要实现这些功能!

暂定规则“类别的名称不允许重复”,则后续在Service层进行处理时,应该先根据尝试添加的类别的名称进行查询,如果查询结果为null,表示此名称对应的类别尚不存在,将允许添加,如果查询结果不为null,表示此名称对应的类别已经存在,将不允许添加!

要实现以上检查的效果,需要执行的SQL语句可以是:

select * from pms_category where name=?;

或者:

select count(*) from pms_category where name=?;

以上2种做法,第1种做法的查询效率相对较低,或者说性能消耗略高,第2种做法的查询性能消耗更低,但是,第1种做法的查询可能具有复用性,而第2种做法的查询的复用性相对较低。

暂定可以使用以上第1种做法。

8.3. 接口与抽象方法

在插入数据之前,需要先创建“类别”对应的实体类型,而这个实体类型不能直接创建在csmall-product-webapi模块中,而是应该创建在另一个新的模块中,以便于其它各模块都可以使用到相同的实体类型(例如商品的实体类型,在商品管理模块和订单管理模块中都将需要使用)。

在Project中创建新的子模块csmall-pojo,创建出来后,需要:

  • 修改父项目

    • csmall-pojopom.xml中修改
    • 在根项目的pom.xml中添加新的<module>
  • 确定所需的依赖项
    • 需要依赖lombok,其它依赖项暂时不需要
  • 删除不要的代码
    • pom.xml中只需要:父项目、当前项目的信息、依赖项
    • 启动类是不需要的,必须删除(因为没有依赖Spring Boot,不删除则报错)
    • src/main/resource是不需要的(包含其下的application.properties),可以删除
    • src/test是不需要的,必须删除(否则默认的测试类会报错)

然后,在cn.tedu.csmall.pojo.entity包下创建Category类:

package cn.tedu.csmall.pojo.entity;

import lombok.Data;

import java.io.Serializable;
import java.time.LocalDateTime; @Data
public class Category implements Serializable { private Long id;
private String name;
private Long parentId;
private Integer depth;
private String keywords;
private Integer sort;
private String icon;
private Integer enable;
private Integer isParent;
private Integer isDisplay;
private LocalDateTime gmtCreate;
private LocalDateTime gmtModified; }

为了实现其它Module可以依赖csmall-pojo,应该先在根级Project的pom.xml中对csmall-pojo实现依赖管理:

<!-- ===== 其它原有代码 ===== -->

<!-- 属性配置,主要配置各依赖项的版本号对应的“变量” -->
<properties>
<!-- ===== 其它原有代码 ===== -->
<csmall.version>0.0.1-SNAPSHOT</csmall.version> <!-- 新增 -->
</properties> <!-- 依赖管理,主要管理各依赖项的版本,使得子级Module添加依赖时不必指定版本 -->
<dependencyManagement>
<dependencies>
<!-- Csmall POJO -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-pojo</artifactId>
<version>${csmall.version}</version>
</dependency> <!-- ===== 其它原有代码 ===== -->

然后,在csmall-product-webapipom.xml中添加依赖:

<!-- ===== 其它原有代码 ===== -->

<!-- 当前项目需要使用的依赖项 -->
<dependencies>
<!-- Csmall POJO -->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-pojo</artifactId>
</dependency> <!-- ===== 其它原有代码 ===== -->

至此,在csmall-product-webapi中就已经成功的依赖了csmall-pojo,可以理解为csmall-pojo已经成为csmall-product-webapi的一部分。

cn.tedu.csmall.product.webapi.mapper包下创建CategoryMapper接口,并在接口上添加@Repository注解(主要是避免IntelliJ IDEA在自动装配时的误判错误),并在接口中添加抽象方法:

/**
* 处理“类别”数据的持久层接口
*/
@Repository
public interface CategoryMapper { /**
* 插入“类别”数据
* @param category 类别
* @return 受影响的行数
*/
int insert(Category category); // 查询--待定 }

8.4. 配置SQL语句

从其它位置(或项目)中复制粘贴CategoryMapper.xmlcsmall-product-webapisrc/main/resources/mapper下。

关于CategoryMapper.xml文件的配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.tedu.csmall.product.webapi.mapper.CategoryMapper"> <!-- int insert(Category category); -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into pms_category (
name, parent_id, depth, keywords, sort,
icon, enable, is_parent, is_display, gmt_create,
gmt_modified
) values (
#{name}, #{parentId}, #{depth}, #{keywords}, #{sort},
#{icon}, #{enable}, #{isParent}, #{isDisplay}, #{gmtCreate},
#{gmtModified}
)
</insert> </mapper>

8.5. 测试

先在src/test下创建resources文件夹,并在此文件夹中创建truncate.sql脚本,此脚本将用于重置数据表:

truncate pms_category;

然后,在src/test/java的根包下创建mapper.CategoryMapperTests,编写并执行测试:

package cn.tedu.csmall.product.webapi.mapper;

import cn.tedu.csmall.pojo.entity.Category;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.jdbc.Sql; @SpringBootTest
public class CategoryMapperTests { @Autowired
CategoryMapper mapper; @Test
@Sql("classpath:truncate.sql")
public void testInsert() {
// 测试数据
Category category = new Category();
category.setName("手机");
// 断言不会抛出异常
assertDoesNotThrow(() -> {
int rows = mapper.insert(category);
assertEquals(1, rows);
assertEquals(1, category.getId());
});
} }

9. 类别管理--添加类别--业务逻辑层

10. 类别管理--添加类别--控制器层

11. 类别管理--添加类别--前端页面

4-7 CS后台项目练习-1的更多相关文章

  1. 4-11 CS后台项目-4 及 Redis缓存数据

    使用Redis缓存数据 使用Redis可以提高查询效率,一定程度上可以减轻数据库服务器的压力,从而保护了数据库. 通常,应用Redis的场景有: 高频查询,例如:热搜列表.秒杀 改变频率低的数据,例如 ...

  2. 4-8 CS后台项目练习-2

    8. 类别管理--添加类别--持久层 8.1. 配置 续前日,无新增 8.2. 规划需要执行的SQL语句 续前日,无新增 8.3. 接口与抽象方法 此前需要执行的SQL语句大致是: select id ...

  3. 4-10 CS后台项目练习-3 || Redis

    13. 类别管理--根据id查询类别详情--持久层 13.1. 规划SQL语句 本次需要执行的SQL语句大致是: select * from pms_category where id=? 关于字段列 ...

  4. CS通用项目系统搭建——三层架构第一天

    CS通用项目:使用三层架构进行搭建 三层架构: 表现层(UI(User Interface)):展示给用户的层面,包含窗体控件数据等信息. 业务逻辑层(BLL(Business Logic Layer ...

  5. php大力力 [039节] 修改一下后台项目,同时启用印象笔记,要做的事情todo列表,记录在印象笔记,速度快一些

    php大力力 [039节]  修改一下后台项目,同时启用印象笔记,要做的事情todo列表,记录在印象笔记,速度快一些

  6. winform WebBrowser控件中,cs后台代码执行动态生成的js

    很多文章都是好介绍C# 后台cs和js如何交互,cs调用js方法(js方法必须是页面上存在的,已经定义好的),js调用cs方法, 但如果想用cs里面执行动态生成的js代码,如何实现呢? 思路大致是这样 ...

  7. 运行PHP后台项目:xampp下载,安装,配置,运行PHP的web项目

    本来没有想着弄PHP,但是有同学叫我帮忙启动一下一个PHP写的后台.着实需要去学习一下. 想着安装xampp软件,一个集合了多个服务器,多个数据库,多个后台语言的管理软件. 一.xampp下载 二.安 ...

  8. react_结合 redux - 高阶函数 - 高阶组件 - 前端、后台项目打包运行

    Redux 独立的集中式状态管理 js 库 - 参见 My Git 不是 react 库,可以与 angular.vue 配合使用,通常和 react 用 yarn add redux import ...

  9. 使用Java+MySQL+Apache开发后台项目(一)

    做前端开发的人越来越多,后端维护的人才越来越稀缺,这种趋势正在慢慢扩展.像我这种人总喜欢反其道而行之,做后端开发的人虽然减少了,但是工作量和工作资质都要求的更高了,随着人工智能的发展,需要后台处理的数 ...

随机推荐

  1. Flume 详解&实战

    Flume 1. 概述 Flume是一个高可用,高可靠,分布式的海量日志采集.聚合和传输的系统.Flume基于流式架构,灵活简单. Flume的作用 Flume最主要的作用就是,实时读取服务器本地磁盘 ...

  2. Citus 11(分布式 PostgreSQL) 文档贡献与本地运行

    Citus 可以使用分片跨多台计算机来水平缩放查询. 其查询引擎会将这些服务器的传入 SQL 查询并行化,加快大型数据集上的响应. 它为需要比其他部署选项更大规模和更高性能的应用程序提供服务:通常,工 ...

  3. iptables系列教程(一)| iptables入门篇

    一个执着于技术的公众号 前言 在早期的 Linux 系统中,默认使用的是 iptables 配置防火墙.尽管新型 的 firewalld 防火墙已经被投入使用多年,但是大量的企业在生产环境中依然出于各 ...

  4. 新鲜出炉:appium2.0+ 单点触控和多点触控新的解决方案

    在 appium2.0 之前,在移动端设备上的触屏操作,单手指触屏和多手指触屏分别是由 TouchAction 类,Multiaction 类实现的. 在 appium2.0 之后,这 2 个方法将会 ...

  5. Go语言学习——函数二 defer语句

    函数 package main import "fmt" // 函数:一段代码的封装 func f1(){ fmt.Println("Hello 中国!") } ...

  6. Nacos源码系列—服务端那些事儿

    点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 nacos,即可免费获取源码 前言 在上节课中,我们讲解了客户端注册服 ...

  7. logging日志模块详细,日志模块的配置字典,第三方模块的下载与使用

    logging日志模块详细 简介 用Python写代码的时候,在想看的地方写个print xx 就能在控制台上显示打印信息,这样子就能知道它是什么 了,但是当我需要看大量的地方或者在一个文件中查看的时 ...

  8. yarn/npm 设置镜像地址

    注意 如果开发 electron 桌面软件,需要设置以下两个镜像地址 disturl.electron_mirror 如果用到了 node-sass 需要设置以下一个镜像地址 sass_binary_ ...

  9. Django序列化组件与数据批量操作与简单使用Forms组件

    目录 SweetAlert前端插件 Django自带的序列化组件 批量数据操作 分页器与推导流程 Forms组件之创建 Forms组件之数据校验 Forms组件之渲染标签 Forms组件之信息展示 S ...

  10. vision transformer

    VIT 总览 Step1 Step2