云商城--业务+架构学习和环境准备

云商城业务+架构学习和环境准备

B2B:Business to Business,交易双方的身份都是商家,也就是商家将商品卖给商家,类似采购、批发类购物,国内代表性网站阿里巴巴批发网

C2C:Customer to Customer,交易双方都可以是个人,比如淘宝网

O2O:Online To Offline,线上线下模式,典型的代表饿了么,在线上支付了,在线下获取商品

B2B2C:大型的电商平台,允许商家入驻,允许会员在平台买卖商品,京东和天猫都属于这类型网站

1.云商城业务场景

1.1 业务学习

​ 云商城是基于SpringCloud Alibaba技术栈研发的B2C电商平台,平台拥有核心的电商业务功能。运营商在后台管理商品,前台能通过搜索引擎实时搜索到最新商品,用户注册后可以直接在平台购买商品,并通过微信支付实现线上支付。用户还能参与平台秒杀抢购,并实现线上支付秒杀商品

1.2 功能学习

1.商品管理

2.商城首页

3.海量商品实时搜索

4.商品及时秒杀

5.购物车管理

6.在线微信支付

2.商城架构设计

云商城采用了微服务技术架构,采用了当前主流的SpringCloud Alibaba技术栈,从接入层、网关层、服务层、数据同步、服务治理、数据处理、第三方接口多个方面进行了精心设计

具体流程:LVS四层负载,抗压能力更强(LVS一般能到达400万并发),然后lvs会把请求路由给nginx七层负载(抗压能力能达到5万)经过了nginx,然后通过网关gateway(路由、限流、鉴权),然后路由到不同的服务(取决于我们的业务),利用分布式事务解决数据不一致性问题,涉及到的数据库包括MySQL、redis、es

3.云商城表结构

3.1 商品数据库

品牌表:brand

sql 复制代码
CREATE TABLE `brand` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '品牌id',
  `name` varchar(100) NOT NULL COMMENT '品牌名称',
  `image` varchar(1000) DEFAULT '' COMMENT '品牌图片地址',
  `initial` varchar(1) DEFAULT '' COMMENT '品牌的首字母',
  `sort` int(11) DEFAULT NULL COMMENT '排序',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=325475 DEFAULT CHARSET=utf8 COMMENT='品牌表';

商品分类表:category

sql 复制代码
CREATE TABLE `category` (
  `id` int(20) NOT NULL AUTO_INCREMENT COMMENT '分类ID',
  `name` varchar(50) DEFAULT NULL COMMENT '分类名称',
  `sort` int(11) DEFAULT NULL COMMENT '排序',
  `parent_id` int(20) DEFAULT NULL COMMENT '上级ID',#这个parent_id就是id,自己查自己,自关联表
  PRIMARY KEY (`id`),
  KEY `parent_id` (`parent_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11177 DEFAULT CHARSET=utf8 COMMENT='商品类目';

品牌分类关联表:category_brand

sql 复制代码
CREATE TABLE `category_brand` (
  `category_id` int(11) NOT NULL COMMENT '分类ID',
  `brand_id` int(11) NOT NULL COMMENT '品牌ID',
  PRIMARY KEY (`brand_id`,`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

商品属性表:sku_attribute

sql 复制代码
CREATE TABLE `sku_attribute` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(50) DEFAULT NULL COMMENT '属性名称',
  `options` varchar(2000) DEFAULT NULL COMMENT '属性选项',
  `sort` int(11) DEFAULT NULL COMMENT '排序',
  `category_id` varchar(100) DEFAULT NULL COMMENT '分类ID集合',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=140 DEFAULT CHARSET=utf8;

商品SPU表:spu

sql 复制代码
CREATE TABLE `spu` (
  `id` varchar(60) NOT NULL COMMENT '主键',
  `name` varchar(100) DEFAULT NULL COMMENT 'SPU名',
  `intro` varchar(200) DEFAULT NULL COMMENT '商品简介',
  `brand_id` int(11) DEFAULT NULL COMMENT '品牌ID',
  `category_one_id` int(20) DEFAULT NULL COMMENT '一级分类',
  `category_two_id` int(10) DEFAULT NULL COMMENT '二级分类',
  `category_three_id` int(10) DEFAULT NULL COMMENT '三级分类',
  `images` varchar(1000) DEFAULT NULL COMMENT '图片列表',
  `after_sales_service` varchar(50) DEFAULT NULL COMMENT '售后服务',
  `content` longtext COMMENT '介绍',
  `attribute_list` varchar(3000) DEFAULT NULL COMMENT '规格列表',
  `is_marketable` int(1) DEFAULT '0' COMMENT '是否上架,0已下架,1已上架',
  `is_delete` int(1) DEFAULT '0' COMMENT '是否删除,0:未删除,1:已删除',
  `status` int(1) DEFAULT '0' COMMENT '审核状态,0:未审核,1:已审核,2:审核不通过',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

商品SKU表:sku

sql 复制代码
CREATE TABLE `sku` (
  `id` varchar(60) NOT NULL COMMENT '商品id',
  `name` varchar(200) NOT NULL COMMENT 'SKU名称',
  `price` int(20) NOT NULL DEFAULT '1' COMMENT '价格(分)',
  `num` int(10) DEFAULT '100' COMMENT '库存数量',
  `image` varchar(200) DEFAULT NULL COMMENT '商品图片',
  `images` varchar(2000) DEFAULT NULL COMMENT '商品图片列表',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `spu_id` varchar(60) DEFAULT NULL COMMENT 'SPUID',
  `category_id` int(10) DEFAULT NULL COMMENT '类目ID',
  `category_name` varchar(200) DEFAULT NULL COMMENT '类目名称',
  `brand_name` varchar(100) DEFAULT NULL COMMENT '品牌名称',
  `sku_attribute` varchar(200) DEFAULT NULL COMMENT '规格',
  `status` int(1) DEFAULT '1' COMMENT '商品状态 1-正常,2-下架,3-删除',
  PRIMARY KEY (`id`),
  KEY `cid` (`category_id`),
  KEY `status` (`status`),
  KEY `updated` (`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';

3.2 订单数据库

订单表:order

sql 复制代码
CREATE TABLE `order` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '订单id',
  `total_num` int(11) DEFAULT NULL COMMENT '数量合计',
  `moneys` int(11) DEFAULT NULL COMMENT '金额合计',
  `pay_type` varchar(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付类型,1、在线支付、0 货到付款',
  `create_time` datetime DEFAULT NULL COMMENT '订单创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '订单更新时间',
  `pay_time` datetime DEFAULT NULL COMMENT '付款时间',
  `consign_time` datetime DEFAULT NULL COMMENT '发货时间',
  `end_time` datetime DEFAULT NULL COMMENT '交易完成时间',
  `username` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '用户名称',
  `recipients` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人',
  `recipients_mobile` varchar(12) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人手机',
  `recipients_address` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '收货人地址',
  `weixin_transaction_id` varchar(30) COLLATE utf8_bin DEFAULT NULL COMMENT '交易流水号',
  `order_status` int(1) COLLATE utf8_bin DEFAULT NULL COMMENT '订单状态,0:未完成,1:已完成,2:已退货',
  `pay_status` int(1) COLLATE utf8_bin DEFAULT NULL COMMENT '支付状态,0:未支付,1:已支付,2:支付失败',
  `is_delete` int(1) COLLATE utf8_bin DEFAULT NULL COMMENT '是否删除',
  PRIMARY KEY (`id`),
  KEY `create_time` (`create_time`),
  KEY `status` (`order_status`),
  KEY `payment_type` (`pay_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

订单明细表:order_sku

sql 复制代码
CREATE TABLE `order_sku` (
  `id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT 'ID',
  `category_one_id` int(11) DEFAULT NULL COMMENT '1级分类',
  `category_two_id` int(11) DEFAULT NULL COMMENT '2级分类',
  `category_three_id` int(11) DEFAULT NULL COMMENT '3级分类',
  `spu_id` varchar(60) COLLATE utf8_bin DEFAULT NULL COMMENT 'SPU_ID',
  `sku_id` varchar(60) COLLATE utf8_bin DEFAULT NULL COMMENT 'SKU_ID',
  `order_id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '订单ID',
  `name` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品名称',
  `price` int(20) DEFAULT NULL COMMENT '单价',
  `num` int(10) DEFAULT NULL COMMENT '数量',
  `money` int(20) DEFAULT NULL COMMENT '总金额',
  `image` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '图片地址',
  PRIMARY KEY (`id`),
  KEY `item_id` (`sku_id`),
  KEY `order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

3.3 秒杀数据库

秒杀商品表:seckill_goods

sql 复制代码
CREATE TABLE `seckill_goods` (
  `id` varchar(60) NOT NULL,
  `sup_id` varchar(60) DEFAULT NULL COMMENT 'spu ID',
  `sku_id` varchar(60) DEFAULT NULL COMMENT 'sku ID',
  `name` varchar(100) DEFAULT NULL COMMENT '标题',
  `images` varchar(150) DEFAULT NULL COMMENT '商品图片',
  `price` int(20) DEFAULT NULL COMMENT '原价格',
  `seckill_price` double(20,0) DEFAULT NULL COMMENT '秒杀价格',
  `create_time` datetime DEFAULT NULL COMMENT '添加日期',
  `start_time` datetime DEFAULT NULL COMMENT '开始时间',
  `end_time` datetime DEFAULT NULL COMMENT '结束时间',
  `num` int(11) DEFAULT NULL COMMENT '秒杀商品数',
  `store_count` int(11) DEFAULT NULL COMMENT '剩余库存数',
  `content` varchar(2000) DEFAULT NULL COMMENT '描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

秒杀订单表:seckill_order

sql 复制代码
CREATE TABLE `seckill_order` (
  `id` varchar(60) NOT NULL COMMENT '主键',
  `seckill_goods_id` varchar(60) DEFAULT NULL COMMENT '秒杀商品ID',
  `money` int(10) DEFAULT NULL COMMENT '支付金额',
  `username` varchar(50) DEFAULT NULL COMMENT '用户',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `pay_time` datetime DEFAULT NULL COMMENT '支付时间',
  `status` int(1) DEFAULT NULL COMMENT '状态,0未支付,1已支付',
  `weixin_transaction_id` varchar(30) DEFAULT NULL COMMENT '交易流水',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.4 用户数据库

省份表:provinces

sql 复制代码
CREATE TABLE `provinces` (
  `provinceid` varchar(20) NOT NULL COMMENT '省份ID',
  `province` varchar(50) NOT NULL COMMENT '省份名称',
  PRIMARY KEY (`provinceid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='省份信息表';

城市表:cities

sql 复制代码
CREATE TABLE `cities` (
  `cityid` varchar(20) NOT NULL COMMENT '城市ID',
  `city` varchar(50) NOT NULL COMMENT '城市名称',
  `provinceid` varchar(20) NOT NULL COMMENT '省份ID',
  PRIMARY KEY (`cityid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='行政区域地州市信息表';

区域表:areas

sql 复制代码
CREATE TABLE `areas` (
  `areaid` varchar(20) NOT NULL COMMENT '区域ID',
  `area` varchar(50) NOT NULL COMMENT '区域名称',
  `cityid` varchar(20) NOT NULL COMMENT '城市ID',
  PRIMARY KEY (`areaid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='行政区域县区信息表';

收件信息表:address

sql 复制代码
CREATE TABLE `address` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL COMMENT '用户名',
  `provinceid` varchar(20) DEFAULT NULL COMMENT '省',
  `cityid` varchar(20) DEFAULT NULL COMMENT '市',
  `areaid` varchar(20) DEFAULT NULL COMMENT '县/区',
  `phone` varchar(20) DEFAULT NULL COMMENT '电话',
  `address` varchar(200) DEFAULT NULL COMMENT '详细地址',
  `contact` varchar(50) DEFAULT NULL COMMENT '联系人',
  `is_default` int(1) DEFAULT NULL COMMENT '是否是默认 1默认 0否',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8;

4.工程搭建

4.1 环境准备

这里需要用到数据库MySQL和注册中心Nacos,数据库和注册中心全部已经安装在了虚拟机中.

properties 复制代码
虚拟机ip:192.168.100.130

虚拟机账号:root

账号密码:pcb

数据库账号:root

数据库密码:123456

Nacos   url   http://192.168.100.130:8848/nacos
              账号:nacos
              密码:nacos

基于Docker安装Nacos:

properties 复制代码
docker run -d -p 8848:8848 -e MODE=standalone -v /opt/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties -v /opt/nacos/logs:/home/nacos/logs --restart always --name nacos nacos/nacos-server

安装好了后,访问http://192.168.100.130:8848/nacos 账号密码都是nacos

基于Docker安装MySQL:

properties 复制代码
docker run -di --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

4.2 工程结构分析

4.3 公共工程搭建

4.3.1 父工程搭建(顶级)

工程坐标:

xml 复制代码
<groupId>com.gupaoedu.vip.mall</groupId>
<artifactId>gupaoedu-vip-mall</artifactId>
<version>0.0.1-SNAPSHOT</version>

我们选择用Spring Initializr创建父工程

选择需要的应用场景

整理下pom.xml,在pom.xml中只留部分包,其他包是创建微服务时需要(所有模块都要用的包)

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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gupaoedu.vip.mall</groupId>
    <artifactId>gupaoedu-vip-mall</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gupaoedu-vip-mall</name>
    <!--父工程-->
    <packaging>pom</packaging>
    <description>云商城</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud-alibaba.version>2.2.1.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencies>
        <!--lombok,方便创建Bean对象和日志操作-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--Test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--热部署插件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <!--alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
4.3.2 子项目父工程创建

我们可以按照功能分类,给每类工程创建一个父工程,方便管理(建maven模块)

properties 复制代码
mall-api:存储所有数据库表对应的Bean和Feign接口
mall-gateway:存储所有微服务网关
mall-service:存储所有微服务工程
mall-util:存储公共工程
mall-web:存储所有和页面渲染有关的工程

mall-api的pom.xml:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gupaoedu-vip-mall</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <artifactId>mall-api</artifactId>
    <description>
        存放所有JavaBean和Feign接口
    </description>
</project>

mall-gateway的pom.xml:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gupaoedu-vip-mall</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <artifactId>mall-gateway</artifactId>
    <description>
        存放微服网关集群
    </description>

</project>

mall-service的pom.xml:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gupaoedu-vip-mall</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <artifactId>mall-service</artifactId>
    <description>所有的应用服务</description>
</project>

mall-util的pom.xml:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gupaoedu-vip-mall</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <artifactId>mall-util</artifactId>
    <description>
        存放所有公共工程
    </description>
</project>

mall-web的pom.xml:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>gupaoedu-vip-mall</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <artifactId>mall-web</artifactId>
    <description>
        存放所有和页面渲染有关的工程,不建议放在service中,所有service只提供基于RESTful的服务
    </description>
</project>
4.3.3 公共工程创建
4.3.3.1 公共依赖汇总

service中以后要创建微服务工程操作数据库,我们可以把所有service需要用到的包以及所有service需要初始化的对象放到一个独立的工程中,以后哪个工程要用,直接依赖即可。

mall-util中创建mall-service-dependency,pom.xml依赖如下:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mall-util</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>mall-service-dependency</artifactId>
    <description>
        所有service工程依赖的包汇总以及初始化工具包
    </description>

    <dependencies>
        <!--web包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--MyBatis Plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>

        <!--MySQL-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--Redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!--Nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
</project>
4.3.3.2 公共工具包

我们需要用到的工具包也可以单独放到一个工程中,每次要用,直接依赖即可

mall-util中创建mall-common,我们在工程中创建2个对象:

用于指定响应状态码的枚举对象:com.gupaoedu.mall.util.RespCode

java 复制代码
public enum RespCode {

    SUCCESS(200, "操作成功"),
    ERROR(500, "操作失败"),
    SYSTEM_ERROR(501, "系统错误");

    private Integer code;
    private String message;

    RespCode(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
    RespCode() {
    }
    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

用于响应用户信息封装的对象:com.gupaoedu.mall.util.RespResult

java 复制代码
public class RespResult<T> implements Serializable {

    //响应数据结果集
    private T data;

    /**
     * 状态码
     * 200 操作成功
     * 500 操作失败
     */
    private Integer code;

    /***
     * 响应信息
     */
    private String message;

    public RespResult() {
    }

    public RespResult(RespCode resultCode) {
        this.code = resultCode.getCode();
        this.message = resultCode.getMessage();
    }

    public RespResult(T data, RespCode resultCode) {
        this.data = data;
        this.code = resultCode.getCode();
        this.message = resultCode.getMessage();
    }
    public static RespResult ok() {
        return new RespResult(null, RespCode.SUCCESS);
    }

    public static RespResult ok(Object data) {
        return new RespResult(data, RespCode.SUCCESS);
    }

    public static RespResult error() {
        return new RespResult(null, RespCode.ERROR);
    }

    public static RespResult error(String message) {
        return secByError(RespCode.ERROR.getCode(),message);
    }

    //自定义异常
    public static RespResult secByError(Integer code,String message) {
        RespResult err = new RespResult();
        err.setCode(code);
        err.setMessage(message);
        return err;
    }

    public static RespResult error(RespCode resultCode) {
        return new RespResult(resultCode);
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
4.3.3.3 依赖管理

service工程一定会依赖mall-service-dependencymall-common,我们可以修改mall-service将这两个工程添加到依赖中:

xml 复制代码
<dependencies>
    <!--依赖mall-service-dependency-->
    <dependency>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <artifactId>mall-service-dependency</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <!--依赖mall-common-->
    <dependency>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <artifactId>mall-common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

5.品牌管理实现

5.1 集成MyBatisPlus

5.1.1 MyBatis Plus介绍

MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

MyBatis Plus特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
5.1.2 MyBatisPlus集成

1)引入依赖包

mall-service-dependency中引入如下依赖(这个依赖包之前已经引入了,这里无需再次引入):

xml 复制代码
<!--MyBatis Plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>

mall-api中引入如下依赖(编写JavaBean会用到MyBatis Plus的相关注解,引入依赖防止程序编译不通过):

xml 复制代码
<!--MyBatis Plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
    <scope>provided</scope>
</dependency>

2)创建goods-api工程

mall-api中创建子工程goods-api,用于创建shop_goods数据库表对应的实体Bean和Feign接口

pom.xml:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mall-api</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>goods-api</artifactId>
    <description>
        shop_goods数据库表对应的JavaBean
    </description>
</project>

goods-api中创建com.gupaoedu.vip.mall.goods.Brand,代码如下:

javaBean与数据库表的对应

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("brand")  //MyBatisPlus表映射注解
public class Brand {

    //品牌ID
    //MyBatisPlus主键策略注解
    @TableId(type = IdType.AUTO)
    private Integer id;
    //品牌名字
    private String name;
    //品牌图片
    private String image;
    //品牌首字母
    private String initial;
    //品牌排序
    private Integer sort;
}

主键生成策略

AUTO 数据库ID自增
NONE 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUT insert前自行set主键值
ASSIGN_ID 分配ID(主键类型为Number(Long和Integer)或String),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
ASSIGN_UUID 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法)
ID_WORKER 分布式全局唯一ID 长整型类型(please use ASSIGN_ID) ,已过时
UUID 32位UUID字符串,已过时
ID_WORKER_STR 分布式全局唯一ID 字符串类型(please use ASSIGN_ID) ,已过时

3)商品微服务

mall-service中创建mall-goods-service微服务,用于操作shop_goods数据库

pom.xml代码如下:

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mall-service</artifactId>
        <groupId>com.gupaoedu.vip.mall</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>mall-goods-service</artifactId>
    <description>
        shop_goods微服务
    </description>

    <dependencies>
        <!--goods-api依赖,需要brand实体类-->
        <dependency>
            <groupId>com.gupaoedu.vip.mall</groupId>
            <artifactId>goods-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

创建bootstrap.yml,配置如下:

yaml 复制代码
server:
  port: 8081
spring:
  application:
    name: mall-goods #服务名
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/shop_goods?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 123456
  cloud:
    nacos:
      config:
        file-extension: yaml
        server-addr: 192.168.1.11:8848
      discovery:
        #Nacos的注册地址
        server-addr: 192.168.1.11:8848
# ====================MybatisPlus====================
mybatis-plus:
  mapper-locations: mapper/*.xml
  type-aliases-package: com.gupaoedu.vip.mall.*.model  #javaBean取别名的位置
  configuration:
    map-underscore-to-camel-case: true  #驼峰命名法,eg:t_user
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

#日志配置
logging:
  pattern:
    console: "%msg%n"

配置说明:

properties 复制代码
type-aliases-package:指定JavaBean的别名包,和MyBatis用法一样
mapper-locations:复杂的操作可能需要自己写SQL,SQL可以写到xml文件中,这里指定和Dao对应的xml文件,此时我们需要在resources中创建一个mapper目录
map-underscore-to-camel-case:开启驼峰功能,数据库表列名如果有_,可以自动按驼峰命名规则转换
log-impl:日志开启,方便测试

创建启动类com.gupaoedu.vip.mall.MallGoodsServiceApplication

java 复制代码
/**
 * 商品服务启动类
 */
@SpringBootApplication
@MapperScan(basePackages = {"com.gupaoedu.vip.mall.goods.mapper"})
public class MallGoodsApplication {

    public static void main(String[] args) {
        SpringApplication.run(MallGoodsApplication.class,args);
    }
}

此时启动程序,查看Nacos控制台:< http://192.168.1.11:8848/nacos/index.html\> 账号和密码都是nacos,效果如下:

5.2 MyBatisPlus操作

我们创建一个品牌操作的功能,实现品牌增删改查,分别创建modelmapperservicecontroller

MyBatisPlus提供了很多通用方法:

properties 复制代码
mapper(接口)->extends BaseMapper【增删改查】
service(接口)->extends IService【增删改查】
serviceImpl->extends ServiceImpl【增删改查】
5.2.1 Mapper创建

mall-goods-service创建com.gupaoedu.vip.mall.goods.mapper.BrandMapper接口,代码如下:

java 复制代码
public interface BrandMapper extends BaseMapper<Brand> {
}

代码说明:BaseMapper中已经存在了很多常见数据库操作方法,可以大幅提升开发速度

5.2.2 Service创建

mall-goods-service创建com.gupaoedu.vip.mall.goods.service.BrandService接口,代码如下:

java 复制代码
public interface BrandService extends IService<Brand>{
}

mall-goods-service创建com.gupaoedu.vip.mall.goods.service.impl.BrandServiceImpl实现类,代码如下:

java 复制代码
@Service
public class BrandServiceImpl extends ServiceImpl<BrandMapper,Brand> implements BrandService {}

代码说明:IServiceServiceImpl中已经创建好了很多常用的增删改查方法,我们写常用的增删改查,几乎不用写方法

5.2.3 增删改功能

增删改功能在IServiceServiceImpl中已经全部存在, 不需要额外添加方法,只需要在Controller调用即可

mall-goods-service创建com.gupaoedu.vip.mall.goods.controller.BrandController,代码如下:

注意:@PathVariable 映射 URL 绑定的占位符,通过 @PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中

java 复制代码
@RestController
@RequestMapping(value = "/brand")
public class BrandController {

    @Autowired
    private BrandService brandService;

    /***
     * 增加品牌  http://localhost:8081/brand
     */
    @PostMapping
    public RespResult add(@RequestBody Brand brand){
        // 增加品牌
        brandService.save(brand);
        return RespResult.ok();
    }

    /****
     * 修改
     */
    @PutMapping
    public RespResult update(@RequestBody Brand brand){
        //修改品牌
        brandService.updateById(brand);
        return RespResult.ok();
    }

    /****
     * 删除品牌
     */
    @DeleteMapping("/{id}")
    public RespResult delete(@PathVariable(value = "id") Integer id){
        //删除品牌
        brandService.removeById(id);
        return RespResult.ok();
    }
}

使用postman测试增删改,增删改mp提供了很多的方法,不需要自己去写,查询有条件查询,需要自己手写

5.2.4 条件查询/分页

条件查询需要封装条件信息,MyBatis Plus提供了条件封装对象Wrapper(它的子类QueryWrapper可以直接使用),我们可以用它的子类QueryWrapper实现封装查询条件

6.2.4.1 条件查询

BrandService中创建如下方法:

List<Brand> queryList(Brand brand);

BrandServiceImpl中创建条件查询方法实现(不要忘了注入brandMapper):

java 复制代码
/**
 * 多条件查询
 */
@Override
public List<Brand> queryList(Brand brand) {
    // 多条件构造器
    QueryWrapper<Brand> queryWrapper = new QueryWrapper<Brand>();
    if(!StringUtils.isEmpty(brand.getName())){
        queryWrapper.like("name",brand.getName());
    }
    if(!StringUtils.isEmpty(brand.getName())){
        queryWrapper.eq("initial",brand.getInitial());
    }
    return brandMapper.selectList(queryWrapper);
}

注意:like:表示模糊查询;eq:表示等值查询

BrandController中创建条件查询方法:

java 复制代码
/**
 * 条件查询
 */
@PostMapping(value = "/list")
public RespResult<List<Brand>> list(@RequestBody(required = false) Brand brand){
    // 查询
    List<Brand> brands = brandService.queryList(brand);
    return RespResult.ok(brands);
}
6.2.4.2 分页查询

BrandService中创建如下方法:

Page<Brand> queryPageList(Long currentPage,Long size,Brand brand);

BrandServiceImpl中创建条件查询方法实现(不要忘了注入brandMapper):

java 复制代码
/***
 * 分页查询
 */
@Override
public Page<Brand> queryPageList(Long currentPage, Long size, Brand brand) {
    // 封装查询条件
    Page<Brand> page = brandMapper.selectPage(
            new Page<Brand>(currentPage, size),
            new QueryWrapper<Brand>()
                    .like("name", brand.getName()));
    return page;
}

BrandController中创建条件查询方法:

java 复制代码
/**
 * 条件分页查询
 */
@PostMapping(value = "/list/{page}/{size}")
public RespResult<Page<Brand>> list(
        @PathVariable(value = "page")Long currentPage,
        @PathVariable(value = "size")Long size,
        @RequestBody(required = false) Brand brand){
    // 分页查询
    Page<Brand> brandPage = brandService.queryPageList(currentPage,size,brand);
    return RespResult.ok(brandPage);
}

测试结果如下:

注意:mp的分页查询,需要写分页拦截器,不然就不起作用

java 复制代码
package com.gupaoedu.vip.mall.config;

@Configuration
public class StartConfig {

    /****
     * 分页插件(分页拦截器),必须写拦截器,不然mp的分页功能不生效
     */
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor pageInterceptor = new PaginationInterceptor();
        // 设置数据类型
        pageInterceptor.setDbType(DbType.MYSQL);
        return pageInterceptor;
    }
}
相关推荐
华年源码6 分钟前
在线商城系统设计与开发-代码(源码+数据库+文档)
java·数据库·毕业设计·源码·springboot
数据的世界018 分钟前
C#标识符和关键字
java·服务器·c#
m0_7482478013 分钟前
【Spring Boot】统一数据返回
java·spring boot·后端
Thomas_YXQ13 分钟前
Unity3D中基于ILRuntime的组件化开发详解
开发语言·网络·游戏·unity·unity3d
星迹日1 小时前
数据结构:包装类和泛型
java·开发语言·数据结构·笔记·泛型·通配符·包装类
鲤籽鲲2 小时前
C# 整型、浮点型 数值范围原理分析
开发语言·c#
重生之绝世牛码3 小时前
Java设计模式 —— 【行为型模式】命令模式(Command Pattern) 详解
java·大数据·开发语言·设计模式·命令模式·设计原则
晚风_END4 小时前
node.js|浏览器插件|Open-Multiple-URLs的部署和使用,实现一键打开多个URL的强大工具
服务器·开发语言·数据库·node.js·dubbo
java排坑日记6 小时前
poi-tl+kkviewfile实现生成pdf业务报告
java·pdf·word
V+zmm101346 小时前
校园约拍微信小程序设计与实现ssm+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm