前言:无意中看到尚硅谷发布了最新的微服务分布式项目《谷粒商城》,刚好最近在学习微服务,所以,想要学习一下。
官方已经发布了相关的资料,但是,可惜的是,并没有课件,只能跟着视频教程一步一步的学习,所以,将目前学习的笔记整理,供自己日后复习,供大家参考。若有不足,还请指正。
一、开发环境统一
0、安装虚拟机、安装MySQL、安装Redis
因为我不打算在我本地电脑上安装这些,所以这条内容省略。
1、Maven
(1)使用阿里镜像仓库
<!-- 阿里镜像仓库-->
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>
http://maven.aliyun.com/nexus/content/groups/public/
</url>
<mirrorOf>central</mirrorOf>
</mirror>
(2)使用jdk1.8编译
<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>
2、安装vscode,并安装相关插件
3、安装配置git
git我之前已经安装过了,这里就不说了。
跟视频一样吧,也使用码云,注册就不说了。
不过,这里要注意一个问题,也就是多个git ssh key 管理问题
不然,会提示:permission denied错误。
因为我之前有其他git账号的ssh key存在,比如GitHub,这里在生成ssh key时,不能一路回车
ssh-keygen -t rsa -C "[email protected]" <<<这里不能一路回车,第一个交互提示要输入存放的路径,不能用默认的,否则会覆盖原来的其他的账号key
下面说下,关于管理多个git ssh key的问题
在.ssh目录创建config文本文件并完成相关配置(最核心的地方)
内容说明如下:
HostName 这个是真实的域名地址
IdentityFile 这里是id_rsa的地址
PreferredAuthentications 配置登录时用什么权限认证--可设为publickey,password publickey,keyboard-interactive等
User 配置使用用户名
这里我的是:
# 配置github.com
Host github.com
HostName github.com
IdentityFile C:\Users\abc\.ssh\github_rsa
PreferredAuthentications publickey
User myname
# 配置gitee.com
Host gitee.com
HostName gitee.com
IdentityFile C:\Users\abc\.ssh\gitee_rsa
PreferredAuthentications publickey
User myname
之后,通过这个命令来测试:ssh -T [email protected]
参考:
https://blog.csdn.net/weixin_36995644/article/details/81776412
https://www.cnblogs.com/popfisher/p/5731232.html
4.项目初始结构创建
在gitee上创建仓库,并且在IDEA中clone,并创建member会员服务,ware仓储服务,order订单服务,product产品服务,coupon优惠券服务,修改.gitignore文件,增加以下内容忽略这些文件的修改。
**/mvnw
**/mvnw.cmd
**/.mvn
**/target/
.idea
**/.gitignore
最后,再把代码提交到gitee仓库中。
5.数据库初始化
根据提供的SQL文件,分别创建gulimall各个表。
二、快速开发-使用人人开源搭建后台管理系统
1.git clone下载renren-fast, renren-fast-vue,renren-generator仓库代码
https://gitee.com/renrenio/renren-fast.git
https://gitee.com/renrenio/renren-fast-vue.gi
https://gitee.com/renrenio/renren-generator.git
2.将renren-fast代码放到gulimall工程目录下面,并在总工程的pom.xml引入renren-fast module.
3.执行renren-fast模块种的db文件下的mysql.sql语句
注意,创建的数据库的基字符集使用utf8mb4。
4.修改renren-fast的application-dev.yml语句中的如下信息
url: jdbc:mysql://172.0.1.xx:3306/gulimall_admin
username: root
password: 123456
启动renren-fast应用
注意,这里遇到一个错误,就是application-dev.yml文件中的com.alibaba.druid.pool.DruidDataSource 显示红色,出错。
另外,一个就是RenrenApplication.java中String标红,显示需要导入包。原来是这个module没有设置对应的jdk,设置一下jdk8就没问题了。
5.安装Node.js,配置npm使用淘宝镜像
npm config set registry http://registry.npm.taobao.org/
6.用vscode打开renren-fast-vue代码,在终端执行:npm install 下载安装依赖,
如果下载出错,可以使用cnpm install 下载,在下载完成后,执行:npm run dev 启动
7.renren-generator代码导入到我们的项目,并启动
8.使用renren-generator结合renren-fast-vue,根据数据库,反向生成product模块代码,并把main文件copy覆盖product下面的main文件夹。
9..新建gulimall-common模块,把公共的API等信息放到common模块中,并解决product中代码引用包的问题。
10.如法炮制,依次使用人人开源产生代码,覆盖main,并导入gulimall-common这类。
11.使用MyBatis-Plus,测试数据库读写问题
(1)导入依赖,在gulimall-common模块的pom.xml中加入:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
(2)在gulimall-product的application.yml文件增加以下内容:
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://172.0.1.xx:3306/gulimall_pms?characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
#driver-class-name: com.mysql.jdbc.Driver
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
(3)在GulimallProductApplicationTests.java中,如下:
@SpringBootTest
class GulimallProductApplicationTests {
@Autowired
BrandService brandService;
@Test
void contextLoads() {
// BrandEntity brandEntity = new BrandEntity();
// brandEntity.setBrandId(4L);
// brandEntity.setDescript("华为");
// brandEntity.setName("华为");
// brandService.save(brandEntity);
// System.out.println("保存成功...");
// brandService.updateById(brandEntity);
List<BrandEntity> list = brandService.list(new QueryWrapper<BrandEntity>().eq("brand_id", 4L));
list.forEach((item) -> {
System.out.println(item);
});
}
}
(4)启动GulimallProductApplicationTests方法,依次测试上面的save方法,update方法,以及遍历方法,可以看到数据库中的数据是正确的。
(5)使用总结
/*
1、整合MyBatis-Plus
(1)、导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
(2)、配置
1、配置数据源
1)、导入数据库的驱动
2)、在application.yml配置数据源相关信息
2、配置Mybatis-Plus
1)、使用MapperScan
2)、告诉MyBatis-Plus,sql映射文件位置
*/
注意,这里有两个问题:
(1)启动整个测试类,application.yml中的driver-class-name: com.mysql.jdbc.Driver 提示报警,应该使用driver-class-name: com.mysql.cj.jdbc.Driver
(2)数据库写入出现乱码,应该把application.yml中的url改为:
url: jdbc:mysql://172.0.1.xx:3306/gulimall_pms?characterEncoding=UTF-8
至此,整个项目基本环境已经弄好了。
三、引入SpringCloudAlibaba组件
1.SpringCloudAlibaba版本引用
在gulimall-common的pom.xml文件中引入spring-cloud-alibaba,如下:
<dependencyManagement>
<!-- spring cloud alibaba 2.1.0.RELEASE -->
<dependencies>
<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>
2.引入Alibaba Nacos注册中心
(1)引入Nacos Discovey,在gulimall-common的pom.xml文件中加上以下内容:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
(2)下载Nacos server,我下载的是1.1.4版本,解压后,执行bin目录下面的startup.cmd文件启动。
(3)在应用中配置指定Nacos server注册中心地址,以gulimall-coupon模块说明,在application.yml文件中添加如下内容:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-coupon
(4)使用@EnableDiscoveryClient注解开启服务注册于发现功能
(5)启动gulimall-coupon服务(注意Nacos Server要先启动),访问本地连接:http://localhost:8848/nacos/#/serviceManagement?dataId=&group=&appName=&namespace=,会看到服务列表里面出现gulimall-coupon
3.在gulimall-member远程调用gulimall-coupon模块的服务
(1)openfeign声明式远程调用引入,在gulimall-member模块的pom.xml文件加入以下内容:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)在CouponController.java加上远程调用的方法实现
@RequestMapping("/member/list")
public R membercoupons() {
CouponEntity couponEntity = new CouponEntity();
couponEntity.setCouponName("满100减50");
return R.ok().put("coupons", Arrays.asList(couponEntity));
}
(3)在gulimall-member模块下,建立一个接口CouponFeignService.java,并写上上面实现的远程调用的API。
package com.atguigu.gulimall.member.feign;
import com.atguigu.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 这是一个声明式的远程调用
*/
@FeignClient("gulimall-coupon")
public interface CouponFeignService {
@RequestMapping("/coupon/coupon/member/list")
public R membercoupons();
}
(4)在GulimallMemberApplication.java中添加@EnableFeignClients(basePackages = "com.atguigu.gulimall.member.feign") ,这个注解的作用是让springcloud扫描com.atguigu.gulimall.member.feign包下的所有接口
/**
* 1、想要远程调用别的服务
* 1)、引入open-feign
* 2)、编写一个接口,告诉SpringCloud这个接口需要调用远程服务
* 1、声明接口的每一个方法都是调用哪个远程服务的那个请求
* 3)、开启远程调用功能
*/
@EnableFeignClients(basePackages = "com.atguigu.gulimall.member.feign")
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallMemberApplication {
public static void main(String[] args) {
SpringApplication.run(GulimallMemberApplication.class, args);
}
}
(5)在gulimall-member模块下的controller数据包写一个测试方法来调用这个远程服务API,比如:在MemberController.java中写一个测试方法,如下:
@Autowired
CouponFeignService couponFeignService;
@RequestMapping("/coupons")
public R test() {
MemberEntity memberEntity = new MemberEntity();
memberEntity.setNickname("张三");
R membercoupons = couponFeignService.membercoupons();
return R.ok().put("member", memberEntity).put("coupons", membercoupons.get("coupons"));
}
(6)启动gulimall-coupon和gulimall-member这两个微服务,访问测试API的地址:http://localhost:8000/member/member/coupons,即可以看到能访问到数据。
4.引入Alibaba Nacos配置中心
(1)导入Nacos配置中心,在gulimall-common的pom.xml文件中加上以下内容:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
(2)gulimall-coupon模块西安的resource目录下新建文件bootstrap.properties,内容如下:
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
(3)在gulimall-coupon模块下的application.properties中加入以下配置:
coupon.user.name=zhangsan
coupon.user.age=18
(4)写测试方法,在CouponController.java中加入以下内容:
@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)启动coupon服务,访问链接:http://localhost:7000/coupon/coupon/test,即可以看到上面的配置
(6)但是,这种方法有一个问题,就是如果配置改变了,需要修改application.properties,并重启coupon微服务,这是个不好的,所以我们引入了Nacos配置中心。根据启动log,微服务可以从nacos读取配置文件信息,默认的是:gulimall-coupon.properties。
(7)在http://localhost:8848/nacos的配置列表中,新建配置,Data Id为:gulimall-coupon.properties,规则就是,应用名.properties,在里面添加任意配置内容,比如:
coupon.user.name=zhangsan2
coupon.user.age=24
(8)在上面的test()方法所在的类上标注@RefreshScope,这样,当Nacos配置中心的gulimall-coupon.properties配置内容修改了,微服务就可以动态的获取到最新的配置信息,并且,这个优先级是高于微服务本身的配置的。
(9)使用Nacos作为配置中心的使用总结如下:
/**
* 1、如何使用Nacos作为配置中心统一管理配置
* 1)、引入依赖
* <dependency>
* <groupId>com.alibaba.cloud</groupId>
* <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
* </dependency>
* 2)、创建一个bootstrap.properties,内容如下:
* spring.application.name=gulimall-coupon
* spring.cloud.nacos.config.server-addr=127.0.0.1:8848
* 3)、需要给配置中心添加一个叫 数据库集(Data Id)gulimall-coupon.properties,默认规则:yingyongming.properties
* 4)、给应用名.properties添加任何配置
* 5)、动态获取配置。
* @RefreshScope:动态获取并刷新配置
* @Value("${配置项的名}"):获取到配置
* 如果配置中心和当前应用的配置文件都配置了相同的项,优先使用配置中心的配置
*
*/
5.Nacos作为配置中心的更多细节用法
(1)为了区分配置和隔离,Nacos引入了几个概念:
- 命名空间,用作配置隔离,默认:public(保留空间):默认新增的所有配置都在public空间,开发,测试,生产:利用命名空间来做环境隔离,或者,每一个微服务之间相互隔离配置,每个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置。
- 配置集以及配置ID,配置集就是所有配置的集合,配置集ID类似文件名,也就是Nacos 中的Data ID。
- 配置分组,默认所有的配置分组都属于:DEFAULT_GROUP,当然,也指定自己的配置分组,比如1111双十一,618之类的。
在之前已经提到,在默认public命名空间,以及使用默认的分组DEFAULT_GROUP里面,创建Data ID:gulimall-coupon.properties,然后在bootstrap.properties文件里面添加指定Nacos的地址,就可以访问默认的gulimall-coupon.properties里面的配置信息了,这个是默认的规则。
但是,如果我们想要用自己的,不是default默认的配置怎么处理呢?
比如还是gulimall-coupon.properties这个Data ID,但是放在了另外一个命名空间,比如是coupon(对应微服务模块的名称,可以每个微服务建立一个对应的命名空间),而且放在了一个prod分组里面(类似的,同一个coupon命名空间下面,还可以建立dev分组,test分组等),那么如何在微服务里面指定访问这个配置呢?答案是:在bootstrap.properties里面添加指定对应的namespace和group,如下:
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=9bc589c6-3f38-470b-af8d-fe84f04770ef
spring.cloud.nacos.config.group=prod
9bc589c6-3f38-470b-af8d-fe84f04770ef是Nacos上coupon命名空间对应的ID值。prod则对应prod这个配置分组,这样,当微服务启动时,如果要获取的配置在Nacos配置中心有(也就是这里的gulimall-coupon.properties)的话,那么就优先使用配置中心的,否则,就会使用代码中application.properties文件的配置。
(2)同时加载多个配置(新的知识点)
注意一下,我们之前是把所有的配置都放在了application.yml中,比如:
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://172.0.1.172:3306/gulimall_sms?characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-coupon
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
server:
port: 7000
但是,如果配置很多的话,都同在同一个文件中的话,不好看,也不便于配置,所以,建议按照不同的作用写到几个配置文件中,而微服务也会从Nacos配置文件中读取配置,并且Nacos也支持多配置文件读取,那么怎么配置使用呢?
在上面我们提到了新建了coupon这个命名空间对应gulimall-coupon这个模块,那么我们把上面的application.yml配置按照不同的功能,拆分为三个配置文件配置到Nacos中,放在coupon命名空间,dev配置分组下面,它们分别是:datasource.yml,内容如下:
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://172.0.1.xx:3306/gulimall_sms?characterEncoding=UTF-8
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis.yml文件,内容如下:
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
global-config:
db-config:
id-type: auto
以及other.yml,内容如下:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
application:
name: gulimall-coupon
server:
port: 7000
而使用的话,很简单,在上面bootstrap.properties文件的基础上增加一下内容:
spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true
spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml
spring.cloud.nacos.config.ext-config[1].group=dev
spring.cloud.nacos.config.ext-config[1].refresh=true
spring.cloud.nacos.config.ext-config[2].data-id=other.yml
spring.cloud.nacos.config.ext-config[2].group=dev
spring.cloud.nacos.config.ext-config[2].refresh=true
分别制定要导入的配置名称,所在的配置分组group,已经是否动态刷新(refresh)。
最好,把application.yml中的配置全部注释掉,启动coupon微服务,来验证配置。可以发现,微服务能够正常读取Nacos中的这三个配置文件。
对于这两部分内容,总结起来就是:
/**
* 1、如何使用Nacos作为配置中心统一管理配置
* 1)、引入依赖
* <dependency>
* <groupId>com.alibaba.cloud</groupId>
* <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
* </dependency>
* 2)、创建一个bootstrap.properties,内容如下:
* spring.application.name=gulimall-coupon
* spring.cloud.nacos.config.server-addr=127.0.0.1:8848
* 3)、需要给配置中心添加一个叫 数据库集(Data Id)gulimall-coupon.properties,默认规则:yingyongming.properties
* 4)、给应用名.properties添加任何配置
* 5)、动态获取配置。
* @RefreshScope:动态获取并刷新配置
* @Value("${配置项的名}"):获取到配置
* 如果配置中心和当前应用的配置文件都配置了相同的项,优先使用配置中心的配置
*
* 2、细节
* 1)、命名空间,配置隔离
* 默认:public(保留空间):默认新增的所有配置都在public空间
* 1、开发,测试,生产:利用命名空间来做环境隔离
* 注意,在bootstrap.properties 配置上,需要使用哪个命名空间下的配置。
* spring.cloud.nacos.config.namespace=32c4a90d-6ac4-4f04-b050-e09bbe7bd58f
* 2、每一个微服务之间相互隔离配置,每个微服务都创建自己的命名空间,只加载自己命名空间下的所
* 有配置
*
* 2)、配置集:所有配置的集合
*
* 3)、配置集ID:类似文件名
* Data ID: 类似文件名
*
* 4)、配置分组:
* 默认所有的配置集都属于:DEFAULT_GROUP
* 1111,618
*
* 每个微服务创建自己的命名空间,使用配置分组区分环境,dev、test、prod
*
* 3、同时加载多个配置文件
* 1)、微服务任何配置信息,任何配置文件都可以放在配置中心中
* 2)、只需要在bootstrp.properties说明加载配置中心那些配置文件即可
* 3)、@Value、@ConfigurationProperties...
* 以上SprintBoot任何方法从配置文件中获取值,都能使用
* 配置中心有的优先使用配置中心中的
*
*/
6.SpringCloud Gateway网关
(1)Gateway网关简单介绍
网关作为流量的入口,常用功能包括路由转发、权限校验、流量控制等,而SpringCloud gateway作为SpringCloud官方推出的第二代网关框架,取代了Zuul网关。
简单一句话总结:先断言(判断请求是否符合某个路由规则),(如果符合了某个路由规则)再路由到指定地方,但在路由之前要先过滤。
官方文档:https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/
(2)引入gulimall-gateway模块
新建gulimall-gateway模块,用Spring Initaliz的方法,并导入gateway模块,建好后,在pom.xml中导入gulimall-common的模块依赖。
<dependency>
<groupId>com.atguigu.gulimall</groupId>
<artifactId>gulimall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
gulimall-gateway模块,同样需要注册到Nacos注册中心和配置中心,下面先弄注册到Nacos注册中心的配置,需要在application.properties文件中指定Nacos注册中心的地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=gulimall-gateway
server.port=88
而要使用Nacos配置中心,需要在bootstrap.properties文件中指定Nacos配置中心的地址:
spring.application.name=gulimall-gateway
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=7df3fe8a-4e08-46d5-8535-da50e6834bfb
这里的7df3fe8a-4e08-46d5-8535-da50e6834bfb是指Nacos配置中心的gateway命名空间所对应的ID。
最后,在application.yml中写上gateway使用的配置规则,比如路由,断言,过滤等。比如:
spring:
cloud:
gateway:
routes:
- id: test_route
uri: https://www.baidu.com
predicates:
- Query=url,baidu
- id: qq_route
uri: https://www.qq.com
predicates:
- Query=url,qq
访问:http://localhost:88/hello?url=qq,就会转到这qq个url地址:https://www.qq.com/hello,同样的,访问:http://localhost:88/hello?url=baidu,就会转到百度的url地址.
至此,关于的SpringCloud Alibaba的基本使用告一段落。
接下来,就是前端的基本知识学习,由于篇幅的限制等原因,就另外开专门开一篇文章来做前端的笔记。
尚硅谷2020微服务分布式电商项目《谷粒商城》(Alibaba+Vue)开发教程学习笔记(二)