第一个 Spring Cloud 微服务程序

Spring Boot 与 Spring Cloud 选型

Spring Cloud 和 Spring Boot 的版本兼容性十分重要,不匹配的版本可能导致功能缺失、依赖冲突等问题。

给出几种常见的版本选项

Spring Boot 2.3.x 与 Spring Cloud Hoxton.SR12

  • 适用场景:适用于对稳定性要求较高,且业务逻辑相对传统,没有大量新兴技术需求的项目。。比如一些企业的内部管理系统,像财务管理系统、人力资源管理系统等,这些系统功能较为固定,注重数据的安全性和业务流程的稳定性。

Spring Boot 2.4.x 与 Spring Cloud 2020.0.3

  • 适用场景:适合有一定规模,需要在微服务架构中逐步引入新技术,对性能和可扩展性有一定要求的项目。比如中型电商平台,需要处理高并发的商品浏览、订单提交等业务,并且可能后续会接入一些新的促销活动模块、个性化推荐服务等。

Spring Boot 3.0.x 与 Spring Cloud 2022.0.3(最常用)

  • 适用场景:适用于完全基于 Java 17 及以上版本进行开发,追求最新技术特性,希望利用最新的 Java 语言特性和微服务框架新功能的项目。比如一些前沿的科研项目相关的管理系统,需要利用最新的技术提升系统性能和开发效率。
  • 特点
    • Spring Boot 3.0.x 基于 Java 17 构建,利用了 Java 17 的新特性,如虚拟线程等,在性能和资源利用上有很大提升,并且全面支持 Jakarta EE 9+ 规范。
    • Spring Cloud 2022.0.3 进一步优化了与 Spring Boot 3.0.x 的兼容性,在服务治理、微服务之间的通信等方面引入了一些新的机制和优化,例如对 gRPC 的集成更加深入,方便在不同语言编写的微服务之间进行高效通信。

项目设计

以一个简单的商品和订单服务为例子,进行微服务项目的演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
FirstCloudDemo/
├── pom.xml # 父项目POM
├── cloud-common/ # 公共模块
│ ├── src/main/java/
│ │ └── edu.software.ergoutree/
│ │ ├── entity/ # 公共实体类
│ │ ├── dto/ # 数据传输对象
│ │ ├── vo/ # 视图对象
│ │ ├── enums/ # 枚举类
│ │ ├── exception/ # 自定义异常
│ │ └── utils/ # 工具类
│ └── pom.xml
├── cloud-gateway/ # 网关服务
│ ├── src/main/java/
│ │ └── edu.software.ergoutree/
│ │ ├── GatewayApplication.java
│ │ ├── config/ # 网关配置
│ │ ├── filter/ # 自定义过滤器
│ │ └── handler/ # 异常处理器
│ ├── src/main/resources/
│ │ ├── application.yml
│ │ └── bootstrap.yml
│ └── pom.xml
├── cloud-user/ # 用户服务
│ ├── src/main/java/
│ │ └── edu.software.ergoutree/
│ │ ├── UserApplication.java
│ │ ├── controller/ # 控制器
│ │ ├── service/ # 业务逻辑
│ │ ├── mapper/ # 数据访问层
│ │ ├── entity/ # 实体类
│ │ └── config/ # 配置类
│ ├── src/main/resources/
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── mapper/ # MyBatis映射文件
│ └── pom.xml
├── cloud-order/ # 订单服务
│ ├── src/main/java/
│ │ └── edu.software.ergoutree/
│ │ ├── OrderApplication.java
│ │ ├── controller/
│ │ ├── service/
│ │ ├── mapper/
│ │ ├── entity/
│ │ ├── feign/ # Feign客户端
│ │ └── config/
│ ├── src/main/resources/
│ │ ├── application.yml
│ │ ├── bootstrap.yml
│ │ └── mapper/
│ └── pom.xml
└── cloud-product/ # 商品服务
├── src/main/java/
│ └── edu.software.ergoutree/
│ ├── ProductApplication.java
│ ├── controller/
│ ├── service/
│ ├── mapper/
│ ├── entity/
│ └── config/
├── src/main/resources/
│ ├── application.yml
│ ├── bootstrap.yml
│ └── mapper/
└── pom.xml

服务间调用关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Client Request

[Gateway:8080] ── 路由分发

┌─────────────────────────────────┐
│ [User Service:8081] │
│ [Product Service:8082] │
│ [Order Service:8083] ←─────────┐│
│ ↓ Feign调用 ││
│ ├─→ User Service (用户信息) ││
│ └─→ Product Service (商品信息) ││
└─────────────────────────────────┘│

Nacos ←─────────────┘
(注册中心+配置中心)

技术选型

  • Spring Boot: 3.2.0
  • Spring Cloud: 2023.0.0
  • Spring Cloud Alibaba: 2023.0.1.0
  • JDK: 21
  • 数据库: MySQL 8.0 + H2(开发环境)
  • 缓存: Redis(可选)

此处使用的是 Spring Cloud Alibaba 作为微服务的注册中心和配置中心,使用 Fegin 作为远程调用,使用Spring Cloud GateWay 作为Api网关,负载均衡使用的是 Ribbon,所以在开始前我们需要下载好 Nacos 组件,方便后面的开发

项目搭建

新建一个空的 maven 项目

image-20250715155810885

去除掉无用的一些目录,只保留 pom.xml

image-20250710102547501

创建微服务模块

以创建 公共模块 cloud-common 为例子

新建微服务模块,我们需要搭建子模块用来编写对应的微服务,和建立单个 Spring Boot 的程序的过程是一样的

image-20250715161057540
image-20250715161239166

去除模块中的无用文件

image-20250715163937671

重复这个过程,就把需要的模块都建好了

image-20250715164855660

依赖管理

父项目 POM (根目录)

来讲解一下父工程的 pom 文件应该如何编写

父工程的 POM 文件需要实现三个核心功能:统一版本管理、声明共用依赖、配置项目继承关系。

所以说父工程POM的主要职责是:

  • 统一管理所有子模块的依赖版本
  • 定义通用的构建配置
  • 声明子模块列表
  • 提供所有子模块都需要的基础依赖

但是到现在为止,这边的新创建的底层父项目只是单独的项目,项目之间并不存在依赖关系,所以这里我们需要将他们改成有依赖关系

所以需要一个版本属性配置,来集中管理所有的依赖版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 版本属性配置:集中管理所有依赖版本 -->
<properties>
<!-- JDK版本 -->
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<!-- Spring Boot 版本 -->
<spring-boot.version>3.2.5</spring-boot.version>

<!-- Spring Cloud 版本 -->
<spring-cloud.version>2023.0.1</spring-cloud.version>

<!-- Spring Cloud Alibaba 版本 -->
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>

<!-- 其他共用依赖版本 -->
<lombok.version>1.18.30</lombok.version>
<mysql-connector.version>8.0.33</mysql-connector.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
</properties>

使用dependencyManagement 只声明版本,不实际引入依赖,也是有必要的

1
2
3
4
5
6
7
8
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM -->
<dependency>
...
</dependency>
</dependencies>
</dependencyManagement>

总的pom文件中增加<modules>标签,代表对应模块的引入:

1
2
3
4
5
6
7
<modules>
<module>cloud-common</module>
<module>cloud-gateway</module>
<module>cloud-user</module>
<module>cloud-product</module>
<module>cloud-order</module>
</modules>

为了更好的管理整个微服务项目,此处我们需要对一些依赖做版本控制,以防止不同服务之间的同一个依赖项出现不同的版本的情况

此外,父工程的 pom 文件需要引入一些共用的依赖,由于依赖的传递性,在此处做引入,其他的地方就不需要再次引入了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<?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">
<modelVersion>4.0.0</modelVersion>

<!-- 父工程基本信息 -->
<groupId>edu.software.ergoutree</groupId>
<artifactId>ErgouCloudShopDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>ErgouCloudShopDemo</name>
<description>Parent project for Ergou Cloud Shop microservices</description>

<!-- 子模块声明(如果已有子模块可在此列出) -->
<modules>
<module>cloud-common</module>
<module>cloud-gateway</module>
<module>cloud-user</module>
<module>cloud-product</module>
<module>cloud-order</module>
</modules>

<!-- 版本属性配置:集中管理所有依赖版本 -->
<properties>
<!-- JDK版本 -->
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<!-- Spring Boot 版本 -->
<spring-boot.version>3.2.5</spring-boot.version>

<!-- Spring Cloud 版本 -->
<spring-cloud.version>2023.0.1</spring-cloud.version>

<!-- Spring Cloud Alibaba 版本 -->
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>

<!-- 其他共用依赖版本 -->
<lombok.version>1.18.30</lombok.version>
<mysql-connector.version>8.0.33</mysql-connector.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
</properties>

<!-- 依赖管理:仅声明版本,不实际引入 -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot 父依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- Spring Cloud 依赖管理 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

<!-- Spring Cloud 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>

<!-- 共用组件版本声明 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>

<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql-connector.version}</version>
</dependency>

<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

<!-- 共用依赖:所有子模块都会继承的依赖 -->
<dependencies>
<!-- Lombok:简化实体类开发 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional> <!-- 允许子模块排除 -->
</dependency>

<!-- Spring Boot 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
  • packaging: pom 类型

  • modules: 定义所有子模块

  • dependencyManagement: 统一管理版本,子模块无需指定版本

  • 版本管理: Spring Cloud、Spring Cloud Alibaba、数据库驱动等

公共模块 POM (cloud-common)

以公共模块为例子,讲解子模块的 pom 文件如何承上启下进行编写

子工程添加这种标签来声明与父项目的继承关系,子模块通过parent标签继承父工程的所有配置。

1
2
3
4
5
<parent>
<groupId>edu.software.ergoutree</groupId>
<artifactId>ErgouCloudShopDemo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

之后,cloud-common模块作为公共模块,包含了微服务项目的基础依赖,其他模块的编写思路也就是差不读的,公共模块的 pom 文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?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>com.ergoutree</groupId>
<artifactId>FirstCloudDemo</artifactId>
<version>1.0.0</version>
</parent>

<artifactId>cloud-common</artifactId>
<name>cloud-common</name>
<description>公共模块</description>

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

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- 用于 JSON 解析,也可用 jjwt-gson -->
<version>0.12.3</version>
<scope>runtime</scope>
</dependency>

<!-- Spring Boot Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

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

<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- Hutool 工具类 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>

<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>

<!-- Spring Cloud OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
  • 包含所有服务共用的依赖,MyBatis Plus、Lombok、工具类等

  • 其他服务通过依赖此模块获得公共功能

网关服务 POM (cloud-gateway)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?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>edu.software.ergoutree</groupId>
<artifactId>ErgouCloudShopDemo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>cloud-gateway</artifactId>
<version>1.0-SNAPSHOT</version>
<name>cloud-gateway</name>
<description>API Gateway for Ergou Cloud Shop</description>

<dependencies>
<!-- Spring Cloud Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<!-- Spring Cloud Alibaba Nacos Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

<!-- Spring Cloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

<!-- Spring Cloud LoadBalancer (Ribbon) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

<!-- Bootstrap 配置处理器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

<!-- Spring Boot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

  • 关键: 使用 spring-cloud-starter-gateway(响应式)
  • 注意: 不能同时引入 spring-boot-starter-web
  • 然后你需要包含负载均衡、熔断器等网关必需组件要什么往里面写什么就可以了

其他三个模块的 pom 文件略

Nacos配置

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

下载之后进入到bin文件目录,点击startup.cmd,启动项目:

image-20250710143458140

需要让你输入一些 nacos 的安全配置,用于不同场景的身份验证和权限控制。分别是生成和验证 JWT 的,用于 Nacos Server 集群间通信时的身份验证和服务身份标识,用于标识当前 Nacos Server 的身份(如集群中的唯一 ID)。

image-20250710143842460

至此,nacos已经启动成功,我们可以访问地址: http://169.254.27.253:8080/index.html 访问nacos的页面。如果需要登录,默认的用户名和密码都是nacos

image-20250710235629676

新建命名空间(主要起环境隔离的作用,不同命名空间不能相互访问)

image-20250715170159826

搭建配置中心配置文件,点击创建配置

image-20250715170238116
image-20250715170408983

这里先只配置端口好,注意不要冲突,同理配出其他的环境

image-20250715170818737

编写每个模块的配置文件

配置网关微服务

编写所需的配置文件

bootstrap.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# bootstrap.yml 比 application.yml 优先加载,用于配置Nacos配置中心等固定的外部化配置

# 服务基本信息配置
spring:
application:
# 服务名称,与注册中心中的服务名一致
name: cloudGateway

# 配置文件相关设置
profiles:
# 激活的环境,可选dev、test、prod等
active: dev

# Spring Cloud相关配置
cloud:
# Nacos 配置中心配置
nacos:
# 配置中心配置
config:
# Nacos服务器地址,开发环境通常是本机,生产环境需修改为实际地址
server-addr: 127.0.0.1:8848
# 配置文件的文件扩展名,目前支持properties和yaml(yml)
file-extension: yaml
# 配置分组,不同环境可以使用不同的配置分组,默认为DEFAULT_GROUP
group: DEFAULT_GROUP
# 命名空间,用于进一步区分不同环境,默认为public
namespace: 7d31e4b6-cfe4-4045-973b-f91847c06442
# 共享配置文件,可以多个服务共享,格式为dataId的完整配置,多个用逗号隔开
shared-configs:
- data-id: common-config.yml # 共享配置文件名称
group: DEFAULT_GROUP # 配置文件所属分组
refresh: true # 是否支持配置动态刷新

# 服务发现配置
discovery:
# Nacos服务器地址,通常与配置中心一致
server-addr: 127.0.0.1:8848
# 命名空间
namespace: 7d31e4b6-cfe4-4045-973b-f91847c06442
# 服务所属分组
group: DEFAULT_GROUP

# 配置Bootstrap上下文加载及优先级
# 在新版本Spring Cloud中,bootstrap上下文默认不加载,需要确保依赖中有spring-cloud-starter-bootstrap

测试一下,可以看到端口已经被更改,启动成功,说明配置中心生效了

image-20250715172623443

此处服务注册成功,说明注册中心配置成功

image-20250715172654095

进行application.yml的配置,在这里最重要的是把网关路由配置配好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# 应用名称和端口配置
server:
port: 8089 # 网关服务端口

spring:
application:
name: cloudGateway # 应用名称

# Spring Cloud Gateway 配置
cloud:
gateway:
# 跨域配置
globalcors:
cors-configurations:
'[/**]': # 对所有请求路径生效
allowed-origins: "*" # 允许的来源,* 表示任何来源
allowed-methods: "*" # 允许的HTTP方法
allowed-headers: "*" # 允许的头信息
allow-credentials: true # 允许携带凭证
max-age: 3600 # 预检请求的有效期,单位为秒

# 默认过滤器配置,对所有路由生效
default-filters:
# - name: RequestSize # 请求大小限制
# args:
# maxSize: 5MB
# - name: Retry # 重试机制
# args:
# retries: 3
# statuses: BAD_GATEWAY

# 路由配置
routes:
# 用户服务路由
- id: user-service-route # 路由ID,必须唯一
uri: lb://cloudUser # 目标URI,lb表示负载均衡,cloudUser是服务名
predicates: # 断言,满足条件的请求会被路由
- Path=/api/user/** # 匹配路径
filters: # 过滤器
- StripPrefix=1 # 去除路径前缀,数字表示去除的路径段数
# - name: CircuitBreaker # 熔断器
# args:
# name: defaultCB
# fallbackUri: forward:/fallback/user

# 商品服务路由
- id: product-service-route
uri: lb://cloud-product
predicates:
- Path=/api/product/**
filters:
- StripPrefix=1

# 订单服务路由
- id: order-service-route
uri: lb://cloud-order
predicates:
- Path=/api/order/**
filters:
- StripPrefix=1

# HTTP客户端配置
httpclient:
connect-timeout: 5000 # 连接超时时间(ms)
response-timeout: 60s # 响应超时时间

# 负载均衡配置
loadbalancer:
ribbon:
enabled: true # 启用Ribbon负载均衡
cache:
ttl: 5s # 缓存存活时间
capacity: 256 # 缓存容量

# Actuator 配置,用于监控和管理应用
management:
endpoints:
web:
exposure:
include: "*" # 暴露所有端点,生产环境建议选择性暴露
endpoint:
health:
show-details: always # 显示详细的健康信息

# 日志配置
logging:
level:
root: INFO # 根日志级别
org.springframework.cloud.gateway: DEBUG # Gateway框架日志级别
org.springframework.http.server.reactive: DEBUG # HTTP服务器反应式日志级别
org.springframework.web.reactive: DEBUG # Web反应式日志级别
reactor.netty: DEBUG # Netty反应式日志级别

# 以下是一些可选配置,根据需要取消注释使用

# Redis配置(如果使用限流、分布式会话等功能)
# spring:
# redis:
# host: localhost
# port: 6379
# database: 0

# 熔断器配置
# resilience4j:
# circuitbreaker:
# instances:
# defaultCB:
# failure-rate-threshold: 50 # 失败率阈值,超过此值触发熔断
# wait-duration-in-open-state: 10000 # 熔断后等待恢复的时间(ms)
# timelimiter:
# instances:
# defaultTL:
# timeout-duration: 5s # 超时时间

# 限流配置
# spring:
# cloud:
# gateway:
# redis-rate-limiter:
# replenishRate: 10 # 令牌桶每秒填充速率
# burstCapacity: 20 # 令牌桶总容量
# requestedTokens: 1 # 每个请求消耗的令牌数

编辑好配置后,直接进行发布

image-20250715172903767

配置其他微服务

在这里以 cloud-user 模块为例子进行配置,实际上和网关的配置大差不差

加入注册中心和配置中心的配置(此处我只讲主体的框架,对于其他的依赖按需要加入,对于公共性的依赖,加入到父模块中更好管理)

加入 nacos 和其他用得上的配置文件

bootstrap.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# bootstrap.yml 优先加载,用于配置Nacos配置中心等固定的外部化配置

# 服务基本信息配置
spring:
application:
# 服务名称,与网关路由中配置的服务名一致
name: cloud-user

# 配置文件相关设置
profiles:
# 激活的环境,可选dev、test、prod等
active: dev

# Spring Cloud相关配置
cloud:
# Nacos 配置中心配置
nacos:
# 配置中心配置
config:
# Nacos服务器地址,与网关配置保持一致
server-addr: 127.0.0.1:8848
# 配置文件的文件扩展名
file-extension: yaml
# 配置分组
group: DEFAULT_GROUP
# 命名空间,与网关配置保持一致
namespace: 7d31e4b6-cfe4-4045-973b-f91847c06442
# 共享配置文件
shared-configs:
- data-id: common-config.yml
group: DEFAULT_GROUP
refresh: true

# 服务发现配置
discovery:
# Nacos服务器地址
server-addr: 127.0.0.1:8848
# 命名空间
namespace: 7d31e4b6-cfe4-4045-973b-f91847c06442
# 服务所属分组
group: DEFAULT_GROUP

application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 应用名称和端口配置
server:
port: 8093 # 用户服务端口
servlet:
context-path: /user # 配置上下文路径,与网关路由的StripPrefix=1配合使用

spring:
application:
name: cloud-user # 应用名称,与bootstrap.yml中保持一致

# 数据库配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/clouduser?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: zjm10086
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 5
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
pool-name: UserHikariCP
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1

# Jackson配置
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
serialization:
write-dates-as-timestamps: false

# MyBatis配置
mybatis-plus:
mapper-locations: classpath:/mapper/**/*.xml
type-aliases-package: com.ergou.cloud.user.entity
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
global-config:
db-config:
id-type: auto
logic-delete-field: is_deleted
logic-delete-value: 1
logic-not-delete-value: 0

# Actuator 配置,用于监控和管理应用
management:
endpoints:
web:
exposure:
include: "*" # 暴露所有端点
endpoint:
health:
show-details: always # 显示详细的健康信息

# 日志配置
logging:
level:
root: INFO
com.ergou.cloud.user: DEBUG

# 自定义用户服务配置
user-service:
default-password: 123456 # 默认密码
token:
secret-key: ergouCloudUserSecret # JWT密钥
expire-time: 7200 # 令牌过期时间(秒)

编辑好配置后,直接进行发布application.yml

image-20250716083758988

为配置添加公共的网关转发前缀

1
2
3
4
server:
port: 8093 # 用户服务端口
servlet:
context-path: /user # 配置上下文路径,与网关路由的StripPrefix=1配合使用

与网关配置相互配合

1
2
3
4
5
6
7
# 用户服务路由
- id: user-service-route
uri: lb://cloud-user
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1

工作原理:

  1. 当请求到达网关时,如 http://gateway:8089/api/user/test/route
  2. 网关根据Path断言匹配到用户服务路由
  3. StripPrefix=1过滤器会去掉路径中的第一段(/api)
  4. 请求转发到用户服务变为 /user/test/route
  5. 用户服务的context-path为/user,所以最终控制器收到的路径是 /test/route

然后创建基本的包结构,写一个简单的控制器在里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package edu.software.ergoutree.clouduser.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
* 测试控制器
* 用于验证配置是否生效
*/
@RestController
@RequestMapping("/test")
@RefreshScope // 支持配置动态刷新
public class TestController {

@Value("${server.port}")
private Integer serverPort;

@Value("${spring.application.name}")
private String applicationName;

@Value("${user-service.default-password:未配置}")
private String defaultPassword;

@Value("${user-service.token.secret-key:未配置}")
private String secretKey;

@Value("${server.servlet.context-path:/}")
private String contextPath;

/**
* 测试配置信息
*/
@GetMapping("/config")
public Map<String, Object> testConfig() {
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("serverPort", serverPort);
result.put("applicationName", applicationName);
result.put("defaultPassword", defaultPassword);
result.put("secretKey", secretKey);
result.put("contextPath", contextPath);
result.put("message", "配置读取成功");
return result;
}

/**
* 健康检查接口
*/
@GetMapping("/health")
public Map<String, Object> health() {
Map<String, Object> result = new HashMap<>();
result.put("status", "UP");
result.put("service", applicationName);
result.put("port", serverPort);
result.put("timestamp", System.currentTimeMillis());
return result;
}

/**
* 测试路由配置
*/
@GetMapping("/route")
public Map<String, Object> testRoute() {
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("message", "成功通过网关路由到用户服务");
result.put("service", applicationName);
result.put("contextPath", contextPath);
result.put("timestamp", System.currentTimeMillis());
return result;
}
}

然后启动项目,进行测试,先启动 gateway 模块,再启动你需要的模块,可以发现配置已经生效

image-20250716085218560

nacos 也能发现对应的服务,这个 cloud-user 服务启动的是一点问题都没有

image-20250716085249028

接下来进行简单的测试,直接访问用户服务: http://localhost:8093/user/test/config 和通过网关访问: http://localhost:8089/user/test/config,两者应该都能访问到接口

image-20250716085357050

对于其他服务也像order一样的去配置,但是应记得服务名和前缀的配置和修改

image-20250716103941634

搭建服务间的调用

新建一个模块 fegin-api,建立如下包结构

image-20250716110215706

fegin-api 模块加入对应的依赖,并且配置 pom.xml 文件,别忘了配置根目录的 pom.xml 文件