谷粒商城基础篇

本文介绍了谷粒商城项目的基础知识,包括项目背景、电商模式(B2B、B2C、C2B、C2C、O2O)以及项目技术栈。项目采用前后分离,基于SpringCloud Alibaba,涉及微服务架构、服务注册发现、配置中心、API网关等。文章详细阐述了环境搭建,如Linux虚拟机、Docker安装、MySQL和Redis的Docker部署。此外,还讨论了MybatisPlus的整合,以及SpringCloud Alibaba中的Nacos作为注册中心和配置中心的使用。
摘要由CSDN通过智能技术生成

typora-root-url: imagetypora-copy-images-to: image---

谷粒商城基础篇

一、项目简介

1.1 项目背景

1.2 电商模式

市面上有 5 种常见的电商模式 B2B、B2B、C2B、C2C、O2O

1.2.1 B2B 模式

B2B(Business to Business),是指商家和商家建立的商业关系,如 阿里巴巴,

1.2.2 B2C 模式

B2C(Business to Consumer) 就是我们经常看到的供应商直接把商品买个用户,即 “商对客” 模式,也就是我们呢说的商业零售,直接面向消费销售产品和服务,如苏宁易购,京东,天猫,小米商城

1.2.3 C2B 模式

C2B (Customer to Business),即消费者对企业,先有消费者需求产生而后有企业生产,即先有消费者提出需求,后又生产企业按需求组织生产

1.2.4 C2C 模式

C2C (Customer to Consumer) 客户之间吧自己的东西放到网上去卖 如 淘宝 咸鱼

1.2.5 O2O 模式

O 2 O 即 Online To Offline,也即将线下商务的机会与互联网结合在一起,让互联网成为线下交易前台,线上快速支付,线下优质服务,如:饿了吗,美团,淘票票,京东到家

1.3 谷粒商城

谷粒商城是一个 B2C 模式的电商平台,销售自营商品给客户

1.4 项目架构图

1、项目微服务架构图

2、微服务划分图

1.5 项目技术&特色

  • 前后分离开发,并开发基于 vue 的 后台管理系统
  • SpringCloud 全新的解决方案
  • 应用监控、限流、网关、熔断降级、等分布式方案,全方位涉及
  • 透彻讲解分布式事务,分布式锁等分布式系统的难点
  • 压力测试与性能优化
  • 各种集群技术的区别以及使用
  • CI/CD 使用

1.6 项目前置要求

学习项目的前置知识

  • 熟悉 SpringBoot 以及常见整合方案
  • 了解 SpringCloud
  • 熟悉 git maven
  • 熟悉 linux、redis docker 基本操作
  • 了解 html,css,js,vue
  • 熟练使用 idea 开发项目

二、分布式基础概念

2.1 微服务

微服务架构风格,就像是把一个单独的应用程序开发成一套小服务,每个小服务运行在自己的进程中,并使用轻量级机制通信,通常是 HTTP API 这些服务围绕业务能力来构建, 并通过完全自动化部署机制来独立部署,这些服务使用不同的编程语言书写,以及不同数据存储技术,并保持最低限度的集中式管理

简而言之,拒绝大型单体应用,基于业务边界进行服务拆分,每个服务独立部署运行。

2.2 集群&分布式&节点

集群是个物理状态,分布式是个工作方式

只要是一堆机器,也可以叫做集群,他不是不是一起协作干活,这谁也不知道,

《分布式系统原理与范型》定义:

“分布式系统是若干独立计算机的集合,这些计算机对于用户来说像但各相关系统”

分布式系统 (distributed system) 是建立网络之上的软件系统

分布式是指讲不通的业务分布在不同的地方

集群实质是将几台服务器集中在一起,实现同一业务

例如:京东是一个分布式系统,众多业务运行在不同的机器上,所有业务构成一个大型的业务集群,每一个小的业务,比如用户系统,访问压力大的时候一台服务器是不够的,我们就应该将用户系统部署到多个服务器,也就是每个一业务系统也可以做集群化

分布式中的每一个节点,都可以做集群,而集群并不一定就是分布式的

节点:集群中的一个服务器

2.3 远程调用

在分布式系统中,各个服务可能处于不同主机,但是服务之间不可避免的需要互相调用,我们称之为远程调用

SpringCloud 中使用 HTTP+JSON 的方式来完成远程调用

2.4 负载均衡

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nG3YCtOA-1646550145444)(image-20201015103547907.png)]

分布式系统中,A 服务需要调用 B 服务,B 服务在多台机器中都存在, A 调用任意一个服务器均可完成功能

为了使每一个服务器都不要太或者太闲,我们可以负载均衡调用每一个服务器,提升网站的健壮性

常见的负载均衡算法:

轮询:为第一个请求选择键康齿中的每一个后端服务器,然后按顺序往后依次选择,直到最后一个,然后循环

最小连接:优先选择链接数最少,也就是压力最小的后端服务器,在会话较长的情况下可以考虑采取这种方式

2.5 服务注册/发现&注册中心

A 服务调用 B 服务, A 服务不知道 B 服务当前在哪几台服务器上有,那些正常的,哪些服务已经下线,解决这个问题可以引入注册中心

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-77WLYs9w-1646550145444)(image-20201015104330935.png)]

如果某些服务下线,我们其他人可以实时的感知到其他服务的状态,从而避免调用不可用的服务

2.6 配置中心

每一个服务最终都有大量配置,并且每个服务都可能部署在多个服务器上,我们经常需要变更配置,我们可以让每个服务在配置中心获取自己的位置。

配置中心用来集中管理微服务的配置信息

2.7 服务熔断&服务降级

在微服务架构中,微服务之间通过网络来进行通信,存在相互依赖,当其中一个服务不可用时,有可能会造成雪崩效应,要防止这种情况,必须要有容错机制来保护服务

1、服务熔断

  • 设置服务的超时,当被调用的服务经常失败到达某个阈值,我们可以开启断路保护机制,后来的请求不再去调用这个服务,本地直接返回默认的数据

2、服务降级

  • 在运维期间,当系统处于高峰期,系统资源紧张,我们可以让非核心业务降级运行,降级:某些服务部处理,或者简单处理【抛异常,返回NULL,调用 Mock数据,调用 FallBack 处理逻辑】

2.8 API 网关

在微服务架构中,API Gateway 作为整体架构的重要组件,他 抽象类服务中需要的公共功能,同时它提供了客户端负载均衡服务自动熔断灰度发布统一认证限流监控日志统计等丰富功能,帮助我们解决很多 API 管理的难题

三、环境搭建

3.1 安装 linux虚拟机

下载&安装 VirtualBox https://www.virtualbox.org/ 要开启 CPU 虚拟化

CPU 查看

下载& 安装 Vagrant

https://app.vagrantup.com/boxes/search Vagrant 官方镜像仓库

https://www.vagrantup.com/downloads.html Vagrant下载

打开window cmd窗口,运行Vagrant init centos/7 ,即可初始化一个centos系统

运行vagrant up即可启动虚拟机。系统root用户的密码是vagrant

vagrant其他常用命令

vagrant ssh 自动使用 vagrant 用户连接虚拟机

vagrant upload source [destination] [name|id] 上传文件

https://www.vagrantup.com/docs/cli/init.html Vagrant 命令行

默认虚拟机的ip 地址不是固定ip 开发不方便

Vagrant 和 VirtualBox 版本有对应问题 都安装最新版本 则安装成功

修改 Vagrantfile

config.vm.network “private_network”, ip: “192.168.56.10”

这里 ip 需要在 物理机下使用 ipconfig 命令找到

3.2 安装 docker

Docker 安装文档参考官网

3.2.1 卸载系统之前安装的 docker

Uninstall old versions

一步一步往下执行就行

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

SET UP THE REPOSITORY

Install the yum-utils package (which provides the yum-config-manager utility) and set up the stable repository.

sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

INSTALL DOCKER ENGINE

  1. Install the latest version of Docker Engine and containerd, or go to the next step to install a specific version:
sudo yum install docker-ce docker-ce-cli containerd.io

Start Docker

sudo systemctl start docker

Verify that Docker Engine is installed correctly by running the hello-world image.

sudo docker run hello-world

设置docker开机自启动

sudo systemctl enable docker 

设置 Docker 镜像加速

登录 aliyun.com 在控制台找到容器镜像服务

3.3 docker 安装 mysql

3.3.1 下载镜像文件
docker pull mysql:5.7
3.3.2 创建实例并启动
# --name指定容器名字 -v目录挂载 -p指定端口映射  -e设置mysql参数 -d后台运行
sudo docker run -p 3306:3306 --name mysql \
-v /mydata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-v /mydata/mysql/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
####
-v 将对应文件挂载到主机
-e 初始化对应
-p 容器端口映射到主机的端口

MySQL 配置

vi /mydata/mysql/conf/my.cnf 创建&修改该文件

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
3.3.3 通过容器的 mysql 命令行工具连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UCQz6Utk-1646550145447)(image-20201015151247976.png)]

3.4 docker 安装 redis

3.4.1 下载镜像文件

docker pull redis

3.4.2 创建实例并启动
 
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf

# 启动 同时 映射到对应文件夹
# 后面 \ 代表换行
docker run -p 6379:6379 --name redis \
-v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf
3.4.3 使用 redis 镜像执行 redis-cli 命令连接

docker exec -it redis redis-cli

持久化 默认 appendonly on 没有开启

vim /mydata/redis/conf/redis.conf
# 插入下面内容
appendonly yes

3.5 开发环境统一

3.5.1 Maven

配置阿里云镜像

<mirrors>
		<mirror>
		<id>nexus-aliyun</id>
		<mirrorOf>central</mirrorOf>
		<name>Nexus aliyun</name>
		<url>http://maven.aliyun.com/nexus/content/groups/public</url>
		</mirror>
	</mirrors>
	

配置 jdk 1.8 编译项目

<profiles>
		<profile>
			<id>jdk-1.8</id>
			<activation>
				<activeByDefault>true</activeByDefault>
				<jdk>1.8</jdk>
			</activation>
			<properties>
				<maven.compiler.source>1.8</maven.compiler.source>
				<maven.compiler.target>1.8</maven.compiler.target>
				<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
			</properties>
		</profile>
	</profiles>
3.5.2 idea&VsCode

idea 安装 lombok、mybatisx插件 Translation插件 等等…

Vscode 安装开发必备插件

Vetur ——语法高亮,智能感知 包含格式化功能,Alt+Shift+F (格式化全文) ,Ctrl+K Ctrl+F (格式化选中代码,两个Ctrl需要同时按着)
EsLint 一一 语法纠错
Auto Close Tag 一一 自动闭合HTML/XML标签
Auto Rename Tag 一一 自动完成另-侧标签的同步修改
JavaScript(ES6) code snippets 一一 ES6 语法智能提示以及快速输入,除j外还支持.ts, .jsx, .tsx, .html, .vue;省去了配置其支持各种包含is代码文件的时间

VsCode开发vue 常用插件

https://blog.csdn.net/yujing1314/article/details/90340647

3.5.3 安装配置 git

1、下载git

https://git-scm.com/

2、配置git 进入 git bash

# 配置用户名
git config --global user.name "user.name"
# 配置邮箱
git config --global user.email "username@email.com" # 注册账号使用的邮箱

3、配置 ssh 免密登录

https://github.com/settings/keys

git bash 使用 ssh-keygen -t rsa -C "XXX@xxx.com" 命令 连续三次回车
一般用户目录下都会有
id_rsa 文件
id_rsa.pub 文件
或者 cat ~/.ssh/id_rsa.pub
登录进 github/gitee 设置 SSH KEY
使用 ssh -T git@gitee.com 测试是否成功
具体过程参考百度
3.5.4 逆向工程使用

1、导入项目逆向工程

2、下载人人开源后台管理系统脚手架工程

  1. 导入工程,创建数据库
  2. 修改工程shiro依赖为SpringSecurity
  3. 删除部分暂时不需要的业务

3、下载人人开源后台管理系统vue端脚手架工程

  1. vscode 导入前端项目
  2. 前后端联调测试基本功能

四、MybatisPlus整合

4.1 配置环境

4.1.1、导入依赖
<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.2.0</version>
        </dependency>
4.2.2、配置数据源

配置数据源

  1. 导入数据库驱动

    https://mvnrepository.com/artifact/mysql/mysql-connector-java

     <!--导入mysql驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.17</version>
            </dependency>
    
  2. 在application.yml配置数据源相关信息
    spring:
      datasource:
        username: root
        password: root
        url: jdbc:mysql://192.168.56.10:3306/gulimall_pms
        driver-class-name: com.mysql.jdbc.Driver
    mybatis-plus:
    	# mapper文件扫描
      mapper-locations: classpath*:/mapper/**/*.xml
      global-config:
        db-config:
          id-type: auto # 数据库主键自增
    

配置MyBatis-Plus包扫描:

  1. 使用@MapperScanner

  2. 告诉MyBatis-Plus,Sql映射文件位置

    @MapperScan("com.atguigu.gulimall.product.dao")
    @SpringBootApplication
    public class GulimallProductApplication {
         
        public static void main(String[] args) {
         
            SpringApplication.run(GulimallProductApplication.class, args);
        }
    }
    

具体过程参考官网: https://baomidou.com/guide/install.html#release

4.2 分页配置

@Configuration // 声明配置类
@EnableTransactionManagement // 开启注解
@MapperScan("com.atguigu.gulimall.product.dao") // 指定扫描包
public class MyBatisConfig {
   


    /**
     * 引入分页插件 拦截器
     * @return
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
   
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
         paginationInterceptor.setOverflow(true);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
         paginationInterceptor.setLimit(1000);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}

4.3 逻辑删除

说明:

只对自动注入的sql起效:

  • 插入: 不作限制
  • 查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
  • 更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段
  • 删除: 转变为 更新

例如:

  • 删除: update user set deleted=1 where id = 1 and deleted=0
  • 查找: select id,name,deleted from user where deleted=0
步骤1:配置 application.yml
mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto # 数据库主键自增
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
步骤2: 实体类字段上加上@TableLogic注解
/**
 * 是否显示[0-不显示,1显示]
 */
@TableLogic(value = "1",delval = "0")
private Integer showStatus;

五、SpringCloud Alibaba

5.1 SpringCloud Alibaba 简介

5.1.1、简介

Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

5.1.2、为什么要使用 ?

SpringClouid的几大痛点:

SpringCloud部分组件停止维护和更新,给开发带来不便;

SpringCloud部分环境搭建复杂,没有完善的可视化界面,我们需要大量的二次开发和定制

SpringCloud配置复杂,难以上手,部分配置差别难以区分和合理应用

SpringCloud Alibaba的优势:

阿里使用过的组件经历了考验,性能强悍,设计合理,现在开源出来大家用

成套的产品搭配完善的可视化界面给开发运维带来极大的便利

搭建简单,学习曲线低。

结合SpringCloud Alibaba我们最终的技术搭配方案:

SpringCloud Alibaba - Nacos : 注册中心 (服务发现/注册)

SpringCloud Alibaba- Nacos: 配置中心 (动态配置管理)

SpringCloud - Ribbon: 负载均衡

SpringCloud - Feign: 声明式HTTP客户端(调用远程服务)

SpringCloud Alibaba - Sentinel: 服务容错(限流、降级、熔断)

SpringCloud - Gateway: API 网关 (webflux 编程模式)

SpringCloud - Sleuth:调用链监控

SpringCloud Alibaba - Seata: 原Fescar, 即分布式事务解决方案

5.2 SpringCloud Alibaba - Nacos [作为注册中心]

Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现,配置管理和服务管理平台,他是使用 java 编写的,需要依赖 java 环境

Nacos 文档地址: https://nacos.io/zh-cn/docs/quick-start.html

5.2.1、下载 nacos-server

https://github.com/alibaba/nacos/releases

5.2.2、启动 nacos-server
  • cmd 运行startup.cmd 文件
  • 访问localhost:8848/nacos/
  • 使用默认的 nacos/nacos 登录

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HrK9OXeh-1646550145448)(image-20201016153720815.png)]

5.2.3、注册进入 nacos 中

1、首先,修改 pom.xml 文件,引入 Nacos Discovery Starter

 <dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
 </dependency>

2、在应用的 /resource /application.properties 中配置 Nacos Server地址

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

3、使用@EnableDiscoveryClient 开启服务注册发现功能

 @SpringBootApplication
 @EnableDiscoveryClient
 public class ProviderApplication {
   

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

4、启动应用、观察 nacos 服务列表是否已经注册上服务

注意每一个应用都应该有名字,这样才能往册上去。修改pplicaion.propertes文件

spring.application.name= service provider
server.port=8000

5、注册更多的服务上去,测试使用 feign 远程

Nacos 使用三步

1、导包

2、写配置,指定 nacos 地址,指定应用的名字

3、开启服务注册发现功能 @EnableDiscoveryClient

Feign 使用三步

1、导包 openfeign

2、开启 @EnableFeignClients 功能

3、编写接口,进行远程调用

5.3 SpringCloud Alibaba - Nacos [作为配置中心]

5.3.1、pom.xml 引入 Nacos Config Starter
  <!--配置中心来做配置管理-->
<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
5.3.2、在应用的 resource 下 bootstrap.properties
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
5.3.3、在 nacos 中添加配置

选择右上角添加配置

Data ID 改成 gulimall-coupon.properties 默认规则 用户名.应用名.properties

5.3.4、在应用中使用@Value 和 @RefreshScope
@RefreshScope // 刷新对应controller
@RestController
@RequestMapping("coupon/coupon")
public class CouponController {
   
    @Autowired
    private CouponService couponService;

    @Value("${coupon.user.name}")
    private String name;

    @Value("${coupon.user.age}")
    private Integer age;
    @RequestMapping("/test")
    public R test() {
   
        return R.ok().put("name",name).put("age",age);
    }

5.3.5、进阶

1、核心概念

命名空间:
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 GroupDatalD 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

配置集

一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。

配置集ID:

Nacos 中的某个配置集的 ID,配置集 ID 是组织划分配置的维度之一,Data ID 通常用于组织划分系统的配置集,一个系统或者应用可以包含多个配置集,一个系统应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识,Data ID 通常采用类 Java 包 如 ( com.taobao.tc.refund.log.level ) 的命名规则保证全局唯一性,此命名规则非强制

配置分组:

Nacos 中的一组配置集,是组织配置的维度之一,通过一个有意义的字符串,(如 Buy 或 Trade ) 对配置集进行分组,从而区分 Data ID 相同的配置集,当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用,DEFAULT_GROUP 配置分组的常见场景,不同的应用或组件采用了相同的配置类型,如 database_url 配置和 MQ_topic 配置

bootstrap.properties 配置

spring.application.name=gulimall-coupon # 服务的名称
spring.cloud.nacos.config.server-addr=127.0.0.1:8848  # 服务注册地址
spring.cloud.nacos.config.namespace=ae34901c-9215-4409-ae61-c6b8d6c8f9b0  # 命名空间地址
#spring.cloud.nacos.config.group=111 # 对应分组

spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml  # 配置集指定data_id
spring.cloud.nacos.config.ext-config[0].group=dev               # 配置集指定 group 分组
spring.cloud.nacos.config.ext-config[0].refresh=true            # 是否动态刷新 在配置中心修改后 微服务自动刷新


相关解释

/**
 * 1、如何使用 Nacos作为配置中心统一管理配置
 *  1.1 引入依赖
 *     <dependency>
 *             <groupId>com.alibaba.cloud</groupId>
 *             <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
 *      </dependency>
 *  1.2 创建一个bootstrap.properties
 *      spring.application.name=gulimall-coupon
 *      spring.cloud.nacos.config.server-addr=127.0.0.1:8848
 *  1.3 需要给配置中心默认添加一个叫 数据集 (Data Id) gulimall-coupon.properties 默认规则 用户名.应用名.properties
 *  1.4 给 应用名.properties 添加任何配置
 *  1.5 动态获取配置
 *      @RefreshScope: 动态获取并刷新配置
 *      @Value$("${配置项的名字}")
 * 如果配置中心和当前应用的配置文件中都配置了相同的配置文件,优先使用配置中心的文件
 *
 * 2、细节
 *      1、命名空间:配置隔离:
 *          默认:public(保留空间);默认新增的所有配置都在 public 空间
 *          1、开发 测试 生产 利用命名空间来做环境隔离
 *          注意: 在bootstrap.properties配置上 需要使用哪个命名空间下的配置
 *              spring.cloud.nacos.config.namespace=b1e89ce0-784f-4a80-9de0-e9b080eeaca5
 *          2、每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置
 *
 *
 *      2、配置集:所有配置的集合
 *
 *      3、配置集ID:类似文件名
 *          Data ID:类型文件名
 *
 *      4、配置分组:
 *      默认所有的配置都属于 DEFAULT_GROUP
 *
 * 每个微服务创建自己的命名空间,使用配置分组区分环境,dev、test、prod
 *
 * 3、同时加载多个配置集
 *      1、微服务任何配置信息,任何配置文件多可以放在配置中心中
 *      2、只要在 bootstrap.properties 说明加载配置中心中哪些配置文件即可
 *      3、@Value,@ConfigurationProperties...
 *      以前SpringBoot的任何方式从配置文件中获取值,都能使用
 *      配置中心有的优先使用配置中心的
 * @author gcq
 * @Create 2020-10-16
 */

5.4 SpringCloud Alibaba-Sentinel

1、简介
1、服务降级限流

什么是熔断:

​ A 服务调用 B 服务的某个功能,由于网络不稳定问题,或者 B 服务卡机,导致功能时间超长,如果这样子的次数太多,我们可以直接将 B 断路了,(A 不在请求 B 接口)凡是调用 B 服务的直接返回降级数据,不必等待 B 的 超时执行,这样 B 的故障问题,就不会级联影响到 A。

什么是降级:

​ 整个网站处于流量高峰期服务器压力剧增,根据当前自身业务情况以及流量,对一些服务和页面进行有策略的降级/停止服务,所有的调用直接返回降级数据以此缓解服务器资源的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户等到正确的响应

异同:

​ 相同点

​ 1、为了保证集群大部分服务的可用性和可靠性,防止崩溃,牺牲小我

​ 2、用户最终都是体验到某个功能不可用

​ 不同点:

​ 1、熔断是被调用方的故障,触发系统的主动规则

​ 2、降级是基于全局的考虑停止一些正常服务,释放资源

什么是限流

​ 对打入的服务的请求流量进行控制,使服务能够承担不超过自己能力的流量压力

2、Sentinel 简介

官方文档:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

项目文档:https://github.com/alibaba/Sentinel

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel 的主要特性:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zxvX7kKg-1646550145448)(/image-20201125115407751.png)]

Sentinel 分为两个部分:

  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

Sentinel 基本概念:

  • 资源
    • 资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
    • 只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
  • 规则
    • 围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
2、Hystrix 与 Sentinel 比较

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U1V90hUq-1646550145449)(/image-20201125120634969.png)]

3、整合 Feign 和 Sentinel 测试熔断降级

熔断降级官网解释:https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

Spring- Cloud整合Sentinel和Feign:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

pom.xml

<!-- 导入sentinel依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--导入openFeign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

application.properties

## sentinel与项目间的通信端口
spring.cloud.sentinel.transport.port=8719
## sentinel端口设置
spring.cloud.sentinel.transport.dashboard=localhost:8333
## 暴露信息
management.endpoints.web.exposure.exclude=*
## 配置文件打开 Sentinel 对 Feign 的支持
feign.sentinel.enabled=true

开启后,在微服务中调用远程服务,Sentinel 就会记录微服务之间的调用,从而对远程调用进行设置熔断降级等。

请求设置

设置流控规则

Feign设置

结果

4、整合 Sentinel 测试限流

官网Spring-Cloud 整合:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

Pom.xml

参考 3、整合 Feign 和 Sentinel 测试熔断降级

控制台:

超过单继阈值,返回自定义请求结果

实现方式:

/**
  		1、代码
 *      	try (Entry entry = SphU.entry("resourceName")) {
 *      	}(BlockedException e){}
 *      2、基于注解
 *       	@SentinelResource(value = "getCurrentSeckillSkusSource",blockHandler = "BlockHandler")
 *       	无论1/2方式一定要配置限流以后的默认返回
 *       	url可以设置统一返回

**/

具体实现方式参考官网给出文档:https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8

5、Sentinel网关限流

官网文档:https://github.com/alibaba/Sentinel/wiki/%E7%BD%91%E5%85%B3%E9%99%90%E6%B5%81

pom.xml

<dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
          <version>2.1.0.RELEASE</version>
</dependency>

启动Sentinle1.7.1 后比原先的1.6.1多个一个功能

您可以在 GatewayCallbackManager 注册回调进行定制:

  • setBlockHandler:注册函数用于实现自定义的逻辑处理被限流的请求,对应接口为 BlockRequestHandler。默认实现为 DefaultBlockRequestHandler,当被限流时会返回类似于下面的错误信息:Blocked by Sentinel: FlowException
@Configuration
public class SentinelGatewayConfig {
   

    public SentinelGatewayConfig() {
   
        GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
   
            // 网关限流了 就会回调
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
   
                R error = R.error(BizCodeEnume.TO_MANY_REQUEST.getCode(), BizCodeEnume.TO_MANY_REQUEST.getMsg());
                String errorJson = JSON.toJSONString(error);
                Mono<ServerResponse> body = ServerResponse.ok().body(Mono.just(errorJson), String.class);
                return body;
            }
        });
    }
}

5.5 SpringCloud Alibaba-Seata

1、简介

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

https://seata.io/zh-cn/index.html

2、核心概念

TC (Transaction Coordinator) - 事务协调者

维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM (Transaction Manager) - 事务管理器

定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM (Resource Manager) - 资源管理器

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

5.6 SpringCloud Alibaba-OSS

5.6.1、简介

对象存储服务 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

5.6.2、使用步骤

使用 Java 上传文件

https://help.aliyun.com/document_detail/32011.html?spm=a2c4g.11186623.6.915.56196d39rr96Ll

来自官网实例 - 上传文件流

  @Test
    public void testUpload() throws FileNotFoundException {
   
        // Endpoint以杭州为例,其它Region请按实际情况填写。
        String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
            // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 //https://ram.console.aliyun.com 创建。
        String accessKeyId = "<yourAccessKeyId>";
        String accessKeySecret = "<yourAccessKeySecret>";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 上传文件流。
        InputStream inputStream = new FileInputStream("<yourlocalFile>");
        ossClient.putObject("<yourBucketName>", "<yourObjectName>", inputStream);

        // 关闭OSSClient。
        ossClient.shutdown();
        System.out.println("上传成功");
    }

需要填写 AccesskeyId 以及 Secret 同时也要指定文件位置 以及文件名字

最终上传结果

5.6.3、 抽取成一个单独的第三方服务?OSS

官网文档

https://github.com/alibaba/aliyun-spring-boot/blob/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample/README-zh.md

新建项目 gulimall-third-party

pom 配置

 <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
 </dependency>

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

application.yml 配置 accessKey、secretKey、endpoint

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    alicloud:
      access-key: LTAI4GE22ckocpNBfd36zkxJ 
      secret-key: qDFrQ6cxZqc4DwxoWx5K2aosXXj0Go
      oss:
        endpoint: oss-cn-shenzhen.aliyuncs.com  ## 地域节点
        bucket: gulimall-oss01 # 桶列表

  application:
    name: gulimall-third-party

server:
  port: 30000
5.6.4、Web端上传介绍

阿里云对象存储-普通上传方式:

用户提交文件到服务器,服务器将文件提交到 OSS 对象存储

和数据直传到OSS相比,以上方法有三个缺点:

  • 上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
  • 扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
  • 费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。

阿里云对象存储-服务端签名后直传:

流程介绍

时序图

背景

采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)时,AccessKey ID和AcessKey Secret会暴露在前端页面,因此存在严重的安全隐患。因此,OSS提供了服务端签名后直传的方案。

Web端向服务端请求签名,然后直接上传,不会对服务端产生压力,而且安全可靠。服务端签后直传

六、SpringCloud

6.1 Feign 声明式远程调用

6.1.1、简介

Feign 是一个声明式的 HTTP 客户端,他的目的就是让远程调用更加简单,Feign提供了 HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好的 HTTP 请求参数、格式、地址等信息

Feign 整合了 Ribbon(负载均衡)和 Hystrix(服务熔断),可以让我们不再需要显示地使用这两个组件

SpringCloud - Feign,在 NetflixFeign 的基础上扩展了对 SpringMVC 注解的支持,在其实现下,我们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定。简化了 SpringCloud - Ribbon 自行封装服务调用客户端的开发量。

6.1.2、使用

1、引入依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、开启 feign 功能

@EnableFeignClients(basePackages = "com.atguigu.gulimall.pms.feign") // 指定feign包位置

3、声明远程接口

@FeignClient("gulimall-ware")
public interface WareFeignService {
   
    
    @PostMapping("/ware/waresku/skus")
    public Resp<List<SkuStockVO>> skuWareInfos(@RequestBody List<Long> skuIds)
}

总结

/**
 * 1、想要远程调用别的服务
 *  1.1 引入open-feing
 *  1.2 编写一个接口,告诉SpringCloud这个接口需要调用的远程服务
 *      1.2.1 生命接口的每一个方法都是调用远程服务的那个请求
 *  1.3 开启远程调用功能
 */

6.2 Gateway

6.2.1、简介

网关作为流浪入口,常用功能包括路由转发,权限效验,限流控制等,而 SpringCloud GateWay作为 SpringCloud 官方推出的第二代网关框架,取代了 Zull 网关

网上测试 三种网关对应请求数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5W6aj0nP-1646550145451)(image-20201016222628121.png)]

网关提供 API 全托管服务,丰富的 API 管理功能,辅助企业管理大规模的 API,以降低管理成本和安全风险、包括协议适配、协议转发、安全策略、防刷、流量、监控日志等功能

Spring Cloud GateWay 旨在提供一种简单有效的方式来对 API 进行路由,并为他们提供切面,列如、安全性、监控/指标 和弹性等

官网文档地址

6.3 Sleuth+Zipkin 服务链路追踪

1、为什么用

微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元。由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位。主要体现在,一个请求可能需要调用很多个服务,而内部服务的调用复杂性,决定了问题难以定位。所以微服务架构中,必须实现分布式链路追踪,去跟进一个请 求到底有哪些服务参与,参与的顺序又是怎样的,从而达到每个请求的步骤清晰可见,出了问题,很快定位。

链路追踪组件有Google 的Dapper, Twitter 的Zipkin,以及阿里的Eagleeye(鹰眼)等,它们都是非常优秀的链路追踪开源组件。

2、基本术语
  • Span (跨度) :基本工作单元,发送一个远程调度任务就会产生一个Span, Span 是一个64位ID唯一标识的,Trace 是用另一个64ID唯一标识的,Span 还有其他数据信息,比如摘要、时间戳事件、Span的ID、 以及进度ID。
  • Trace (跟踪) :一系列Span组成的一个树状结构。请求一个微服务系统的API接口,这个API接口,需要调用多个微服务,调每个微服务都会产生一个新的Span,所有由这个请求产生的Span组成了这个Trace
  • Annotation (标注) :用来及时记录一个事件的,一些核心注解用来定义一个请求的开始和结束。这些注解包括以下:
    • cs- Client Sent客户端发送一 个请求,这个注解描述了这个Span的开始
    • sr- Server Received -服务端获得请求并准备开始处理它,如果将其sr诚去cs时间戳便可得到网络传输的时间。
    • ss- Server Sent(服务端 发送响应) -该注解表明请求处理的完成(当请求返回客户端),如果ss的时间戳诚去sr时间戳,就可以得到服务器请求的时间。
    • cr- Client Received (客 户端接收响应)此时Span的结束,如果cr的时间戳诚去cs时间戳便可以得到整个请求所消耗的时间。

官方文档:

https://docs.spring.io/spring-cloud-sleuth/docs/2.2.5.RELEASE/reference/html/

如果调用顺序是这样的

3、整合 Sleuth

1、服务提供者与消费者导入依赖

  <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-sleuth</artifactId>
    </dependency>

2、打开 debug 日志

3、发起一次远程调用,观察控制台

4、整合 zipkin 可视化观察

通过 Sleuth 产生的调用链监控信息,可以得知微服务之间的调用链路,但监控信息只输出到控制台不方便查看,我们需要一个图形化的工具 -Zipkin ,Zipkin 是 Twitter 开源的分布式跟踪系统,主要用来收集系统的时序数据,从而追踪链路的调用问题,zipkin 官网地址如下:

https://zipkin.io/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qqQclDpg-1646550145452)(/image-20201127111241744.png)]

1、docker 安装 zipkin服务器

docker run -d -p 9411:9411 openzipkin/zipkin

2、pom.xml

<dependency> 
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

3、application.yml

# zipkin查询服务器实例的URL
spring.zipkin.base-url=http://192.168.56.10:9411/
# 不查询自己
spring.zipkin.discovery-client-enabled=false
# 发送类型
spring.zipkin.sender.type=web
# 应用采样的请求概率
spring.sleuth.sampler.probability=1
5、Zipkin 数据持久化

Zipkin默认是将监控数据存储在内存的,如果Zipkin挂掉或重启的话,那么监控数据就会丢失。所以如果想要搭建生产可用的Zipkin,就需要实现监控数据的持久化。而想要实现数据持久化,自然就是得将数据存储至数据库。好在Zipkin 支持将数据存储至:

内存(默认)

MySQL

Elasticsearch

Cassandra

Zipkin 数据持久化相关官方文档地址如下

七、前端开发基础知识

这个等以后深入学习在进行记录~~~~

7.1 VSCode 使用

Get

	"http-get请求": {
		"prefix": "httpget",
		"body": [
		"this.\\$http({",
		"url: this.\\$http.adornUrl(''),",
		"method: 'get',",
		"params: this.\\$http.adornParams({})",
		"}).then(({ data }) => {",
		"})"],
		"description": "httpGET请求"
	},

POST

	"http-post请求": {
		"prefix": "httppost",
		"body": [
		"this.\\$http({",
		"url: this.\\$http.adornUrl(''),",
		"method: 'post',",
		"data: this.\\$http.adornData(data, false)",
		"}).then(({ data }) => { });" ],
		"description": "httpPOST请求"
	}

7.2 ES6

7.3 Node.js

7.4 Vue

7.4.5 整合 Element UI

1、安装

npm i element-ui -S

2、引入 Element

main.js 中引入以下内容

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'; // 引入静态资源文件
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
  el: '#app',
  render: h => h(App)
});

7.5 Babel

7.6 Webpack

八、商品服务&三级分类

8.1 基础概念

8.1.1、三级分类

一级分类查出二级分类数据,二级分类中查询出三级分类数据

数据库设计

8.1.2、SPU 和 SKU

SPU:Standard Product Unit (标准化产品单元)

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aEePWTKs-1646550145453)(/image-20201020083615056.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i8f7uAlH-1646550145453)(/image-20201020083857519.png)]

IPhoneX 是 SPU,MI8 是 SPU

IPhoneX 64G 黑曜石 是 SKU

MIX8 + 64G 是 SKU

SKU: Stock KeepingUnit (库存量单位)

8.1.3、基本属性 【规格参数】与 销售属性

每个分共下的商共享规格参数、与销售属性,只是有些商品不一定更用这个分类下全部的属性:

属性是以三级分类组织起来的

规格参数中有些是可以提供检索的

规格参数也是基本属性,他们具有自己的分组

属性的分组也是以三级分类组织起来的

属性名确定的,但是值是每一个商品不同来决定的

【属性分组-规格参数-销售属性-三级分类】关联关系

SPU-SKU-属性表

8.1.4、接口文档位置

https://easydoc.xyz/s/78237135/ZUqEdvA4/hKJTcbfd

8.1.5、 Object 划分
1、PO (persistant object) 持久化对象

po 就是对应数据库中某一个表的一条记录,多个记录可以用 PO 的集合,PO 中应该不包含任何对数据库到操作

2、DO ( Domain Object) 领域对象

就是从现实世界抽象出来的有形或无形的业务实体

3、TO (Transfer Object) 数据传输对象

不同的应用程序之间传输的对象

4、DTO (Data Transfer Object) 数据传输对象

这个概念来源于 J2EE 的设计模式,原来的目的是为了 EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分数调用的性能和降低网络负载,但在这里,泛指用于展示层与服务层之间的数据传输对象

5、VO(value object) 值对象

通常用于业务层之间的数据传递,和 PO 一样也是仅仅包含数据而已,但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要,用 new 关键字创建,由 GC 回收

view Object 试图对象

接受页面传递来的数据,封装对象,封装页面需要用的数据

6、BO(business object) 业务对象

从业务模型的角度看,见 UML 原件领域模型中的领域对象,封装业务逻辑的, java 对象,通过调用 DAO 方法,结合 PO VO,进行业务操作,business object 业务对象,主要作用是把业务逻辑封装成一个对象,这个对象包括一个或多个对象,比如一个简历,有教育经历,工作经历,社会关系等等,我们可以把教育经历对应一个 PO 、工作经验对应一个 PO、 社会关系对应一个 PO, 建立一个对应简历的的 BO 对象处理简历,每 个 BO 包含这些 PO ,这样处理业务逻辑时,我们就可以针对 BO 去处理

7、POJO ( plain ordinary java object) 简单无规则 java 对象

传统意义的 java 对象,就是说一些 Object/Relation Mapping 工具中,能够做到维护数据库表记录的 persisent object 完全是一个符合 Java Bean 规范的 纯 java 对象,没有增加别的属性和方法,我们的理解就是最基本的 Java bean 只有属性字段 setter 和 getter 方法

POJO 时是 DO/DTO/BO/VO 的统称

8、DAO(data access object) 数据访问对象

是一个 sun 的一个标准 j2ee 设计模式,这个模式有个接口就是 DAO ,他负持久层的操作,为业务层提供接口,此对象用于访问数据库,通常和 PO 结合使用,DAO 中包含了各种数据库的操作方法,通过它的方法,结合 PO 对数据库进行相关操作,夹在业务逻辑与数据库资源中间,配合VO 提供数据库的 CRUD 功能

8.2 三级分类接口编写

// 返回查询所有分类以及子子分类,以树形结构组装起来    
List<CategoryEntity> listWithTree();

实现类:

  @Override
    public List<CategoryEntity> listWithTree() {
   
        // 1、查出所有分类 设置为null查询全部
        List<CategoryEntity> entities = baseMapper.selectList(null);

        // 2、组装成父子的树形结构
        List<CategoryEntity> levelList = entities.stream().filter(categoryEntity -> {
   
            // parentCid ==0 为父目录默认0
            return categoryEntity.getParentCid() == 0;
        }).map(menu -> {
   
            // 设置二三级分类 递归
            menu.setChildren(getChildrens(menu,entities));
            return menu;
        }).sorted((menu1, menu2) -> {
   
            //  排序 Sort字段排序
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());

        return levelList;
    }

  /**
     *  递归查询子分类
     * @param root 当前category对象
     * @param all  全部分类数据
     * @return
     */
    private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {
   

        List<CategoryEntity> collect = all.stream().filter(categoryEntity -> {
   
            // 遍历所有的category对象的父类id = 等于root的分类id 说明是他的子类
            return categoryEntity.getParentCid() == root.getCatId();
        }).map(menu -> {
   
            // 1、递归遍历菜单
            menu.setChildren(getChildrens(menu, all));
            return menu;
        }).sorted((menu1, menu2) -> {
   
            // 2、菜单排序
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());

        return collect;
    }

跨域

跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;

下图详细说明了 URL 的改变导致是否允许通信

跨域流程

浏览器发请求都要实现发送一个请求询问是否可以进行通信 ,我直接给你返回可以通信不就可以了吗?

相关资料参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

解决跨越( 一 ) 使用nginx部署为同一域

开发过于麻烦,上线在使用

解决跨域 ( 二 )配置当次请求允许跨域

1、添加响应头

  • Access-Control-Allow-Origin: 支持哪些来源的请求跨域

  • Access-Control-Allow-Methods: 支持哪些方法跨域

  • Access-Control-Allow-Credentials: 跨域请求默认不包含cookie,设置为true可以包含cookie

  • Access-Control-Expose-Headers: 跨域请求暴露的字段

    ​ CORS请求时, XML .HttpRequest对象的getResponseHeader()方法只能拿到6个基本字段: CacheControl、Content-L anguage、Content Type、Expires、

    Last-Modified、 Pragma。 如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

  • Access-Control-Max- Age: 表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一-请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

网关配置文件

        - id: product_route
          uri: lb://gulimall-product
          predicates:
            - Path=/api/product/**
          filters:
            - RewritePath=/api/(?<segment>/?.*),/$\{
   segment}

        - id: admin_route
          uri: lb://renren-fast  # lb负载均衡
          predicates:
            - Path=/api/**  # path指定对应路径
          filters: # 重写路径
            - RewritePath=/api/(?<segment>/?.*), /renren-fast/$\{
   segment}

跨越设置

请求先发送到网关,网关在转发给其他服务 事先都要注册到注册中心

@Configuration
public class GulimallCorsConfiguration {
   

    @Bean
    public CorsWebFilter corsWebFilter() {
   
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();

        // 配置跨越
        corsConfiguration.addAllowedHeader("*"); // 允许那些头
        corsConfiguration.addAllowedMethod("*"); // 允许那些请求方式
        corsConfiguration.addAllowedOrigin("*"); //  允许请求来源
        corsConfiguration.setAllowCredentials(true); // 是否允许携带cookie跨越
        // 注册跨越配置
        source.registerCorsConfiguration("/**",corsConfiguration);

        return new CorsWebFilter(source);
    }

}
8.2.1 树形展示三级分类数据

1、用到的前端组件 Tree 树形控件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a3ME7pBn-1646550145454)(image-20201018160751922.png)]

<el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
<!--
data	展示数据
props 配置选项
	children 指定子树为节点对象的某个属性值
	label 指定节点标签为节点对象的某个属性值
    disabled 节点选择框是否禁用为节点对象的某个属性值
@node-click 节点被点击时的回调
-->

配置静态数据就能显示出对应的效果

2、编写方法获取全部菜单数据

getMenus()<
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值