# SpringCloud创建指南
**Repository Path**: homeless20/spring-cloud-creation-guide
## Basic Information
- **Project Name**: SpringCloud创建指南
- **Description**: SpringCloud快速上手(有SpringBoot基础后)
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-06-25
- **Last Updated**: 2026-06-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring Cloud 微服务项目创建指南
> 基于 Spring Boot 3.4.x + Spring Cloud 2024.0.x,适合零基础快速上手。
---
## 目录
1. [项目架构总览](#1-项目架构总览)
2. [技术栈与版本选型](#2-技术栈与版本选型)
3. [项目目录结构](#3-项目目录结构)
4. [第一步:创建父工程 POM](#4-第一步创建父工程-pom)
5. [第二步:创建公共模块 common](#5-第二步创建公共模块-common)
6. [第三步:创建服务注册中心 Eureka](#6-第三步创建服务注册中心-eureka)
7. [第四步:创建服务提供者 Provider](#7-第四步创建服务提供者-provider)
8. [第五步:创建服务消费者 Consumer (Feign)](#8-第五步创建服务消费者-consumer-feign)
9. [第六步:创建 API 网关 Gateway](#9-第六步创建-api-网关-gateway)
10. [启动与测试](#10-启动与测试)
11. [核心概念速查](#11-核心概念速查)
12. [常见问题与解决方案](#12-常见问题与解决方案)
---
## 1. 项目架构总览
```
┌─────────────────────┐
│ 外部客户端/浏览器 │
└──────────┬──────────┘
│ 全部请求发往 :8080
▼
┌─────────────────────┐
│ API 网关 Gateway │
│ (端口 8080) │
│ 路由 + 负载均衡 │
└──────┬──────┬───────┘
│ │
┌────────────┘ └────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Consumer 消费者 │ │ Provider 提供者 │
│ 订单服务 :8082 │──Feign 调用──▶│ 用户服务 :8081 │
│ (调用用户服务) │ │ (提供用户 API) │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ 注册 / 发现 │
└────────┐ ┌────────────┘
▼ ▼
┌──────────────────────────┐
│ Eureka 注册中心 :8761 │
│ 服务注册 / 服务发现 │
└──────────────────────────┘
```
**五个模块各自职责:**
| 模块 | 端口 | 角色 | 核心能力 |
|---|---|---|---|
| `spring-cloud-common` | - | 公共库 | 统一返回结果、DTO 定义 |
| `spring-cloud-eureka` | 8761 | 注册中心 | 服务注册/发现、健康检查 |
| `spring-cloud-gateway` | 8080 | API 网关 | 路由转发、负载均衡、统一入口 |
| `spring-cloud-provider` | 8081 | 服务提供者 | 提供用户 CRUD API |
| `spring-cloud-consumer` | 8082 | 服务消费者 | 通过 Feign 调用 Provider |
---
## 2. 技术栈与版本选型
**版本匹配是 Spring Cloud 项目中最容易踩坑的地方。**
Spring Cloud 与 Spring Boot 有严格的版本对应关系:
| Spring Cloud 版本 | 对应的 Spring Boot 版本 |
|---|---|
| 2024.0.x (Moorgate) | 3.4.x |
| 2023.0.x (Leyton) | 3.3.x |
| 2022.0.x (Kilburn) | 3.0.x / 3.1.x |
本项目的选择:
| 组件 | 版本 | 说明 |
|---|---|---|
| Java | 17 | Spring Boot 3.x 最低要求 |
| Spring Boot | 3.4.6 | 基础框架,内嵌 Tomcat |
| Spring Cloud | 2024.0.1 | 微服务全家桶 |
| Eureka | 内嵌在 Cloud 中 | 服务注册与发现 |
| OpenFeign | 内嵌在 Cloud 中 | 声明式 HTTP 调用 |
| Gateway | 内嵌在 Cloud 中 | 响应式 API 网关 |
| LoadBalancer | 内嵌在 Cloud 中 | 客户端负载均衡 |
**关键 Maven 概念:**
```xml
...
...
```
---
## 3. 项目目录结构
```
Spring_Cloud_Test/test1/
│
├── pom.xml # 【父工程 POM】统一版本管理
│
├── spring-cloud-common/ # 【公共模块 - 纯 JAR 库】
│ ├── pom.xml
│ └── src/main/java/com/example/springcloud/common/
│ ├── dto/
│ │ └── UserDto.java # 用户数据传输对象
│ └── result/
│ └── Result.java # 统一返回结果封装
│
├── spring-cloud-eureka/ # 【服务注册中心】
│ ├── pom.xml
│ └── src/main/
│ ├── java/.../eureka/
│ │ └── EurekaServerApplication.java
│ └── resources/
│ └── application.yml
│
├── spring-cloud-gateway/ # 【API 网关】
│ ├── pom.xml
│ └── src/main/
│ ├── java/.../gateway/
│ │ └── GatewayApplication.java
│ └── resources/
│ └── application.yml
│
├── spring-cloud-provider/ # 【服务提供者 - 用户服务】
│ ├── pom.xml
│ └── src/main/
│ ├── java/.../provider/
│ │ ├── ProviderApplication.java
│ │ ├── entity/
│ │ │ └── User.java # 用户实体
│ │ ├── controller/
│ │ │ └── UserController.java
│ │ └── service/
│ │ ├── UserService.java
│ │ └── impl/
│ │ └── UserServiceImpl.java
│ └── resources/
│ └── application.yml
│
└── spring-cloud-consumer/ # 【服务消费者 - 订单服务】
├── pom.xml
└── src/main/
├── java/.../consumer/
│ ├── ConsumerApplication.java
│ ├── controller/
│ │ └── OrderController.java
│ ├── service/
│ │ ├── OrderService.java
│ │ └── impl/
│ │ └── OrderServiceImpl.java
│ ├── feign/
│ │ └── UserFeignClient.java # ★ Feign 接口(核心)
│ └── fallback/
│ └── UserFeignFallback.java # 服务降级
└── resources/
└── application.yml
```
---
## 4. 第一步:创建父工程 POM
**作用:** 统一管理所有子模块的依赖版本,避免版本冲突。
**文件:** `pom.xml`(项目根目录)
### 4.1 核心要素
```xml
4.0.0
com.example
spring-cloud-demo
1.0.0
pom
spring-cloud-common
spring-cloud-eureka
spring-cloud-gateway
spring-cloud-provider
spring-cloud-consumer
17
3.4.6
2024.0.1
org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.projectlombok
lombok
true
```
### 4.2 关键知识点
**`import` 的作用:**
Spring Boot 和 Spring Cloud 都提供了自己的 BOM(Bill of Materials),用 `scope=import` 导入后,你引入它们的依赖时就不需要写版本号,版本由 BOM 统一管理。例如引入 `spring-boot-starter-web` 时无需写 ``。
**⚠️ 什么东西不该放在父 POM 的 `` 里?**
- `spring-boot-starter-web`(Servlet MVC)—— 因为 Gateway 模块需要的是 WebFlux,两者冲突
- 只在部分模块使用的依赖——应该由各子模块自行声明
**⚠️ 最容易出现的错误:**
父 POM 统一引入 `spring-boot-starter-web` → Gateway 模块报错 `Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway`。解决方案:将 web 依赖从父 POM 移除,让 provider 和 consumer 各自引入。
---
## 5. 第二步:创建公共模块 common
**作用:** 存放所有微服务共用的代码,避免代码重复。
### 5.1 POM 配置
```xml
com.example
spring-cloud-demo
1.0.0
spring-cloud-common
jar
```
### 5.2 统一返回结果 `Result.java`
```java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private int code; // 200 = 成功,其他 = 失败
private String message; // 提示信息
private T data; // 泛型数据
// 快速构建成功/失败响应
public static Result ok(T data) {
return new Result<>(200, "success", data);
}
public static Result fail(int code, String message) {
return new Result<>(code, message, null);
}
}
```
**设计原则:**
- 所有 Controller 返回 `Result`,前端收到统一格式的 JSON
- 泛型 `` 支持返回任意类型的数据
- 静态工厂方法 `Result.ok(data)` 比 `new Result(...)` 更语义化
### 5.3 DTO(数据传输对象)
DTO 与 Entity 的区别:
- **Entity**:与数据库表对应,不能随意修改
- **DTO**:只包含需要传输的字段,解耦前后端和微服务之间
---
## 6. 第三步:创建服务注册中心 Eureka
**作用:** 所有微服务把地址注册到这里,调用方从这里发现目标服务。
**比喻:** 电话黄页 —— 公司注册号码,需要联系时先查黄页。
### 6.1 POM 依赖
```xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
```
### 6.2 启动类
```java
@SpringBootApplication
@EnableEurekaServer // ★ 关键注解:启动 Eureka 注册中心
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
```
### 6.3 配置文件
```yaml
server:
port: 8761 # Eureka 默认端口
spring:
application:
name: eureka-server # 服务名称
eureka:
client:
register-with-eureka: false # ★ 自己就是注册中心,不注册自己
fetch-registry: false # ★ 不从自己拉取服务列表
service-url:
defaultZone: http://localhost:8761/eureka/
server:
enable-self-preservation: false # 开发环境关闭自我保护
```
### 6.4 验证方式
启动后访问 `http://localhost:8761`,看到 Eureka 控制台即表示成功。
---
## 7. 第四步:创建服务提供者 Provider
**作用:** 提供具体的业务 API,并注册到 Eureka。
### 7.1 POM 依赖
```xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
com.example
spring-cloud-common
```
### 7.2 启动类
```java
@SpringBootApplication
@EnableDiscoveryClient // 开启服务发现(注册到 Eureka)
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
```
### 7.3 配置文件
```yaml
server:
port: 8081
spring:
application:
name: user-service # ★ 服务名:这名字很重要,Consumer 用这个名字调用
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
```
### 7.4 Controller 示例
```java
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
public Result getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
if (user == null) {
return Result.fail(404, "用户不存在");
}
return Result.ok(convertToDto(user));
}
}
```
---
## 8. 第五步:创建服务消费者 Consumer (Feign)
**作用:** 通过 OpenFeign 声明式调用 Provider,演示微服务间通信。
**这是 Spring Cloud 最重要的学习点之一。**
### 8.1 POM 依赖
```xml
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-loadbalancer
```
### 8.2 启动类
```java
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.example.springcloud.consumer.feign") // ★
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
```
### 8.3 Feign 接口(核心)
```java
@FeignClient(
name = "user-service", // ★ 目标服务名 = Provider 的 spring.application.name
path = "/user", // 公共路径前缀
fallback = UserFeignFallback.class // 降级类
)
public interface UserFeignClient {
@GetMapping("/{id}") // 等价于调用 GET http://user-service/user/{id}
Result getUserById(@PathVariable("id") Long id);
@GetMapping("/list")
Result> listAllUsers();
}
```
**Feign 调用背后发生了什么?**
```
1. Consumer 调用 userFeignClient.getUserById(1L)
│
2. Feign 动态代理拦截调用
│
3. 根据 name="user-service" 去 Eureka 查询服务实例列表
│
4. LoadBalancer 通过轮询算法选择一个实例(如 192.168.1.5:8081)
│
5. 拼装 URL:GET http://192.168.1.5:8081/user/1
│
6. 发送 HTTP 请求,获取 JSON 响应
│
7. 将 JSON 反序列化为 Result 返回
```
**你不需要写一行 HTTP 调用代码!这就是"声明式调用"的含义。**
### 8.4 服务降级 Fallback(容错)
```java
@Component
public class UserFeignFallback implements UserFeignClient {
@Override
public Result getUserById(Long id) {
return Result.fail(503, "用户服务暂时不可用(已降级)");
}
}
```
当 Provider 宕机或超时,不会直接报 500 错误给用户,而是返回降级后的友好提示,防止雪崩效应。
### 8.5 配置文件
```yaml
server:
port: 8082
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
```
---
## 9. 第六步:创建 API 网关 Gateway
**作用:** 所有外部请求的统一入口,将请求路由到对应的微服务。
### 9.1 ⚠️ Gateway 最关键的问题
**Gateway 基于 WebFlux(响应式),与 spring-boot-starter-web(Servlet MVC)冲突!**
- 父 POM 不要引入 `spring-boot-starter-web`
- Gateway 自己的 POM 也不要引入
- `spring-cloud-starter-gateway` 自带 WebFlux
### 9.2 POM 依赖
```xml
org.springframework.cloud
spring-cloud-starter-gateway
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
```
### 9.3 启动类
```java
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
```
### 9.4 路由配置(核心)
```yaml
spring:
cloud:
gateway:
routes:
# --- 路由规则 1:用户服务 ---
- id: user-service-route
uri: lb://user-service # lb = Load Balance,服务名必须在 Eureka 中存在
predicates:
- Path=/api/user/** # 匹配 /api/user/xxx 的请求
filters:
- StripPrefix=1 # 去掉 /api,/api/user/1 → /user/1 转发
# --- 路由规则 2:订单服务 ---
- id: order-service-route
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- StripPrefix=1
```
**路由规则解读:**
| 客户端请求 | 匹配的路由 | 去掉前缀后 | 实际转发到 |
|---|---|---|---|
| `/api/user/1` | user-service-route | `/user/1` | `lb://user-service/user/1` |
| `/api/user/list` | user-service-route | `/user/list` | `lb://user-service/user/list` |
| `/api/order/create` | order-service-route | `/order/create` | `lb://order-service/order/create` |
---
## 10. 启动与测试
### 10.1 启动顺序(重要!)
```
第 1 步:启动 spring-cloud-eureka —— 注册中心必须先启动
第 2 步:启动 spring-cloud-provider —— 服务提供者注册到 Eureka
第 3 步:启动 spring-cloud-consumer —— 服务消费者注册到 Eureka
第 4 步:启动 spring-cloud-gateway —— 网关最后启动,接收外部请求
```
### 10.2 启动命令
```bash
# 在项目根目录(test1/)执行
# 方式一:一次编译全部模块
mvn clean package -DskipTests
# 方式二:分别启动各模块
cd spring-cloud-eureka && mvn spring-boot:run &
cd spring-cloud-provider && mvn spring-boot:run &
cd spring-cloud-consumer && mvn spring-boot:run &
cd spring-cloud-gateway && mvn spring-boot:run &
```
### 10.3 验证各组件
| 验证内容 | 访问地址 | 预期结果 |
|---|---|---|
| Eureka 控制台 | `http://localhost:8761` | 看到 3 个服务:GATEWAY, USER-SERVICE, ORDER-SERVICE |
| Provider 直连 | `http://localhost:8081/user/1` | 返回用户张三的信息 |
| Consumer 直连 | `http://localhost:8082/order/user/1` | 通过 Feign 获取用户张三 |
| Consumer 创建订单 | `POST http://localhost:8082/order/create?userId=1&productName=iPhone` | 返回订单 + 用户信息 |
| 网关 → 用户服务 | `http://localhost:8080/api/user/1` | 经网关路由到 user-service |
| 网关 → 订单服务 | `http://localhost:8080/api/order/user/1` | 经网关路由到 order-service |
| Feign 降级测试 | 停掉 Provider 后访问 Consumer | 返回 503 + 降级提示 |
### 10.4 测试调用链
```bash
# 最完整的调用链:浏览器 → 网关 → 消费者 → Feign → 提供者
curl "http://localhost:8080/api/order/create?userId=1&productName=iPhone"
# 返回示例:
{
"code": 200,
"message": "success",
"data": {
"success": true,
"orderId": 1719345678000,
"productName": "iPhone",
"user": {
"id": 1,
"username": "张三",
"email": "zhangsan@example.com",
"phone": "13800000001"
}
}
}
```
**这个调用经历了:**
```
浏览器
→ Gateway (路由匹配 + 负载均衡)
→ order-service (Consumer)
→ Feign (声明式调用)
→ Eureka (服务发现 + 负载均衡)
→ user-service (Provider 返回数据)
```
---
## 11. 核心概念速查
### 11.1 服务注册与发现
```
Provider 启动 → 向 Eureka 注册自己的 IP:端口 → Consumer 从 Eureka 查到 Provider 地址 → 发起调用
```
- **注册:** 服务启动时告诉 Eureka "我在这里,IP 是 X,端口是 Y"
- **发现:** 调用方从 Eureka 获取目标服务的实例列表
- **心跳:** 服务每 30 秒向 Eureka 发一次心跳,Eureka 90 秒收不到心跳就剔除该服务
### 11.2 OpenFeign 声明式调用
| 传统方式 | Feign 方式 |
|---|---|
| `RestTemplate.getForObject("http://192.168.1.5:8081/user/1", ...)` | `userFeignClient.getUserById(1L)` |
| 需要自己写 URL,硬编码 IP 和端口 | 只需写接口 + 注解,Feign 自动生成实现 |
| 需要自己处理负载均衡 | 自动集成 LoadBalancer |
| 需要自己序列化/反序列化 JSON | 自动处理 |
### 11.3 负载均衡
客户端负载均衡(Spring Cloud LoadBalancer):
1. 从 Eureka 拿到 Provider 的所有实例:`[192.168.1.5:8081, 192.168.1.6:8081, 192.168.1.7:8081]`
2. 通过轮询算法选择一个实例
3. 将请求发送到选中的实例
4. 下次请求选下一个实例(轮询)
### 11.4 API 网关
网关 = 小区的门卫,所有访客(请求)都要经过门卫:
- **路由:** 根据路径将请求分发到对应的服务
- **统一鉴权:** 在网关层做登录验证,不需要每个服务都验证一遍
- **跨域处理:** 在网关统一处理 CORS
- **限流:** 控制请求频率,防止服务被打垮
### 11.5 服务降级与熔断
| 概念 | 说明 | 类比 |
|---|---|---|
| **降级 (Fallback)** | 被调服务不可用时,返回兜底结果 | 餐厅某道菜卖完了,推荐你另一道菜 |
| **熔断 (Circuit Breaker)** | 错误率达到阈值时,直接切断调用,快速失败 | 保险丝过载断开,防止火灾 |
| **限流 (Rate Limit)** | 控制单位时间内的请求数量 | 景区限流,每天只卖 3 万张票 |
---
## 12. 常见问题与解决方案
### 12.1 Gateway 报错:Spring MVC incompatible
**错误信息:**
```
Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway.
```
**原因:** 父 POM 或 Gateway 模块引入了 `spring-boot-starter-web`(Servlet MVC),与 Gateway 的 WebFlux 冲突。
**解决:**
1. 父 POM 不引入 `spring-boot-starter-web`
2. 让 Provider 和 Consumer 各自引入
3. Gateway 只用 `spring-cloud-starter-gateway`(自带 WebFlux)
### 12.2 Eureka 上看到服务但 Feign 调用失败
**可能原因:**
- 服务名大小写不一致(Eureka 将服务名转为大写,但 Feign 的 name 区分大小写)
- Feign 接口的 `@RequestMapping` 路径与 Provider 的路径不匹配
- 未引入 `spring-cloud-starter-loadbalancer`
### 12.3 Feign 超时
Feign 默认超时时间很短(约 1 秒),复杂业务容易超时:
```yaml
spring.cloud.openfeign.client.config.default:
connect-timeout: 5000 # 连接超时 5 秒
read-timeout: 5000 # 读取超时 5 秒
```
### 12.4 Eureka 自我保护机制
Eureka 控制台出现红色警告 `EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP...`
这是 Eureka 的自我保护机制:短时间内大量服务心跳丢失时,Eureka 不会立即剔除它们,防止因网络波动误删健康服务。
开发环境建议关闭:`eureka.server.enable-self-preservation: false`
---
## 附:版本对应关系速查表
| Spring Boot | Spring Cloud | Java | 备注 |
|---|---|---|---|
| 3.5.x | 2025.0.x | 17+ | 最新版 |
| 3.4.x | 2024.0.x | 17+ | 本项目使用 |
| 3.3.x | 2023.0.x | 17+ | 上一代 |
| 3.0.x-3.1.x | 2022.0.x | 17+ | - |
| 2.7.x | 2021.0.x | 8/11 | 大量存量项目 |
| 2.3.x-2.4.x | Hoxton | 8 | 已停止维护 |
---
> **学习建议:**
> 1. 按启动顺序依次启动各模块,逐个验证
> 2. 在 Controller 中打断点,观察调用链
> 3. 停掉 Provider 模拟故障,观察 Feign 降级效果
> 4. 在 Eureka 控制台观察服务的上线/下线
> 5. 尝试新增一个服务,练习 Feign 调用和 Gateway 路由配置