Spring Cloud 开发入门:环境搭建与微服务项目实战(上)
一、开发环境搭建
1. JDK 安装与版本选择
版本选择解析
Java 是 Spring Cloud 微服务开发的基础,选择合适的 JDK 版本至关重要,特别是在框架兼容性和生产环境稳定性方面。
(1)主流 JDK 版本对比
版本 | 发布年份 | 支持状态 | 特点简述 |
---|---|---|---|
JDK8 | 2014 | 已过高峰期 | 最广泛使用、兼容性强、生态成熟,是旧项目的首选 |
JDK11 | 2018 | LTS(长期支持) | 模块系统正式引入,提升性能,支持较新特性,企业应用常用 |
JDK17 | 2021 | LTS(当前主流) | JDK17 是 Spring Boot 3.x 的最低要求,稳定性好,现代语法支持增强 |
JDK21 | 2023 | LTS | 最新 LTS,支持更多语言特性(如模式匹配、虚拟线程等),但部分框架支持仍在完善 |
(2)为何选择 LTS 版本
-
**长期支持(LTS)**版本通常每三年发布一次,官方和社区提供更长周期的安全更新与 bug 修复。
-
对于企业级微服务系统,LTS 是最佳选择,避免频繁升级带来的风险与成本。
-
非 LTS 版本(如 JDK9、JDK13)生命周期短,适合尝鲜,不适合生产。
(3)JDK 与 Spring Boot / Spring Cloud 兼容性对照表
Spring Boot 版本 | 支持的最低 JDK | Spring Cloud 版本 | 推荐 JDK 版本 |
---|---|---|---|
2.3.x ~ 2.7.x | JDK8 | Hoxton / 2020.x / 2021.x | JDK8 / JDK11 |
3.0.x ~ 最新 | JDK17 | 2022.x / 2023.x / 2024.x | JDK17+ |
-
Spring Boot 3.x 是一次重大版本升级:
-
移除对 JDK8 和 JDK11 的支持
-
依赖 Jakarta EE 9(包名变更),与旧项目不兼容
-
-
使用 Spring Boot 3.x + Spring Cloud 202x.x 版本,必须选择 JDK17 或更高版本
总结建议
-
初学者或新项目推荐直接使用 JDK17(LTS)
-
有长期维护计划的企业项目建议选择 JDK17 或 JDK21
-
老项目如使用 Spring Boot 2.x,可继续使用 JDK8 / JDK11,但建议预留升级路径
-
为何选择 JDK17
1. Spring Boot 3.x 的最低要求
自 Spring Boot 3.0 起,官方已明确要求 最低 JDK 版本为 17,原因包括:
-
Spring Framework 6 基于 Jakarta EE 9+(包名由
javax.*
改为jakarta.*
),需要更现代的 Java 环境支持; -
JDK8/11 已无法满足 Spring 生态的长期发展需求;
-
Spring Boot 3.0 起全面提升性能、安全标准,需 JDK17 提供底层支持。
2. JDK17 的优势
维度 | 优势说明 |
---|---|
语法支持 | 支持 sealed classes、records、switch 增强(preview) 等现代特性 |
性能优化 | 改进 GC、类数据共享、JIT 编译器等,提升启动速度与运行时效率 |
安全性 | 更强的默认模块封装和类访问控制,降低依赖泄漏和反射攻击风险 |
稳定性 | 属于 LTS(长期支持)版本,官方和大多数云平台提供稳定支持 |
兼容性 | 已被大多数主流框架支持:Spring Boot 3.x、Spring Cloud、MyBatis、Hibernate 等 |
3. 生产环境成熟度
JDK17 自 2021 年发布以来,已经经过多个版本修复和稳定迭代,适用于大中型微服务系统的生产部署。很多主流云服务平台(如 AWS、Alibaba Cloud)均默认提供 JDK17 运行环境。
实操指南:安装与配置 JDK17
1. 安装方式
可根据操作系统选择合适的方式安装:
-
Windows
-
推荐使用 Adoptium 提供的 MSI 安装包(Temurin 是开源且稳定的分发版本)
-
安装过程中可勾选自动配置环境变量选项
-
-
macOS
-
使用 Homebrew 安装:
brew install openjdk@17
然后添加环境变量:
echo 'export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc echo 'export JAVA_HOME="/opt/homebrew/opt/openjdk@17"' >> ~/.zshrc source ~/.zshrc
-
-
Linux(Ubuntu / CentOS)
-
Ubuntu 示例:
sudo apt update sudo apt install openjdk-17-jdk
-
CentOS 示例:
sudo yum install java-17-openjdk-devel
-
2. 官方下载链接
-
OpenJDK 17 官方页面:JDK 17 Releases
3. 环境变量配置(通用说明)
-
设置
JAVA_HOME
环境变量:-
Windows:设置为
C:\Program Files\Java\jdk-17
-
macOS/Linux:通常为
/opt/homebrew/opt/openjdk@17
或/usr/lib/jvm/java-17-openjdk
-
-
将
$JAVA_HOME/bin
加入到PATH
中
这方面不懂得可以看 第一段代码 (大佬写的博客):
Java基础1-环境篇:JDK安装与环境变量配置-CSDN博客
4. 验证安装成功
打开终端或命令行,执行以下命令验证:
java -version
输出示例:
java version "17.0.9" 2024-04-16 LTS
OpenJDK Runtime Environment (build 17.0.9+9)
OpenJDK 64-Bit Server VM (build 17.0.9+9, mixed mode, sharing)
javac -version
输出示例:
javac 17.0.9
2. MySQL 安装
微服务背景下数据库的角色
在传统的单体应用架构中,所有模块通常共享一个数据库。这种模式虽然方便集中管理,但在 可维护性、可扩展性和部署隔离性 上存在明显短板。
而在微服务架构中,数据库不再是全局共享资源,而是服务内部的组成部分。每个服务不仅是代码独立、部署独立,其数据也应当是独立的,这被称为 服务自治(Service Autonomy)原则。
1. 每个微服务拥有独立的数据源
-
每个微服务拥有自己的数据库实例或数据库 schema,不直接访问其他服务的数据;
-
服务之间通过 API / 消息中间件 进行数据交互,而不是跨库查询;
-
这种模式可以有效避免服务间耦合、数据一致性强依赖等问题。
✅ 优点:
-
数据结构可以根据服务需求灵活调整
-
服务间无需协调即可独立升级或迁移数据库
-
降低数据库访问冲突和锁表风险
❌ 代价:
-
带来分布式事务、数据同步等额外挑战(需依赖 MQ、事件总线或 Saga 模式等)
2. 数据库按业务模块划分(示例)
假设我们正在开发一个电商系统,其中包含以下服务:
微服务 | 数据库示例 | 说明 |
---|---|---|
用户服务 | user_service_db | 存储用户信息、登录凭证、注册信息等 |
订单服务 | order_service_db | 存储订单主表、订单项、支付状态等 |
商品服务 | product_service_db | 商品目录、库存、分类、价格等 |
支付服务 | payment_service_db | 第三方支付记录、交易日志等 |
这种划分方式能确保每个服务对自己的数据拥有完全控制权,同时提升整体系统的解耦度与可扩展性。
3. 服务间数据同步的正确姿势
若某服务需要依赖另一个服务的数据,不应直接访问其数据库,而应:
-
调用对方服务提供的 RESTful API / RPC 接口
-
使用 消息队列(如 Kafka / RabbitMQ) 异步监听数据变更
-
通过 缓存(如 Redis) 实现数据同步副本供只读访问
MySQL 安装指南
在微服务项目中,MySQL 作为关系型数据库的主流选择,兼具 易用性、稳定性和社区支持,非常适合中小型系统的数据存储需求。
1. 推荐版本:MySQL 8.x
-
为何推荐 MySQL 8.x?
-
原生支持 JSON 字段与函数,方便微服务传输结构化数据
-
更强的性能优化(如更高效的索引、查询计划优化器)
-
默认字符集为
utf8mb4
,支持完整 Unicode(含 Emoji) -
安全性提升:默认密码策略、角色权限模型更完善
-
-
版本兼容提醒:
-
Spring Boot 3.x 默认使用
mysql-connector-j 8.x
驱动,推荐配套使用 MySQL 8.x 服务端 -
若仍使用 MySQL 5.x,需手动调整 JDBC 配置(如
useSSL
,serverTimezone
)
-
2. 适配系统安装方式
Windows 系统
-
安装方式:
-
前往官网下载安装程序:https://dev.mysql.com/downloads/installer/
-
推荐选择:MySQL Installer (Community Edition),支持一键安装 Server + Workbench + Shell
-
-
安装建议:
-
自定义安装路径(避免带空格的目录)
-
初始配置时设置好 root 密码、默认端口(3306)与字符集(选
utf8mb4_general_ci
)
-
-
自动服务启动:
-
可配置为开机自动启动 MySQL 服务
-
macOS 系统
-
推荐方式:使用 Homebrew 安装
brew update brew install mysql brew services start mysql
-
初始化与登录
mysql_secure_installation # 安全配置向导,设置 root 密码等 mysql -u root -p # 登录 MySQL
-
Homebrew 路径问题提示
-
若命令不可用,尝试添加 PATH:
echo 'export PATH="/opt/homebrew/opt/mysql/bin:$PATH"' >> ~/.zshrc source ~/.zshrc
-
Linux 系统
-
Ubuntu / Debian 系
sudo apt update sudo apt install mysql-server sudo systemctl start mysql sudo mysql_secure_installation
-
CentOS / RedHat
sudo yum install @mysql sudo systemctl start mysqld sudo grep 'temporary password' /var/log/mysqld.log sudo mysql_secure_installation
-
默认安装后使用
mysql -u root -p
登录,建议立即修改 root 密码、禁用匿名用户等。
✅ 小贴士:确认安装成功
mysql --version
示例输出:
mysql Ver 8.0.36 for Linux on x86_64 (MySQL Community Server - GPL)
没有安装的可以看博主之前写的博客:
MYSQL_安装与配置(超详细,仅需一篇就能帮你成功安装MYSQL)-CSDN博客
数据库初始化配置
MySQL 安装完成后,为了支持微服务场景中的多语言、Emoji、连接池高并发等需求,需要对数据库进行一定的初始化配置。以下是推荐的配置实践。
1. 设置默认字符集为 utf8mb4
-
utf8mb4
是真正支持完整 Unicode 的字符集,兼容 Emoji 和多国语言字符。 -
默认字符集在 MySQL 8.x 中已从
latin1
提升为utf8mb4
,但仍建议手动确认或设置:
修改配置文件(通常位于 /etc/my.cnf
或 /etc/mysql/my.cnf
):
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
重启 MySQL 服务后执行:
SHOW VARIABLES LIKE 'character_set%';
确认输出中 character_set_server
和 character_set_database
为 utf8mb4
。
2. 创建数据库用户与权限配置
示例 SQL:为微服务创建独立用户并开放访问权限(仅用于开发环境,生产建议最小权限原则)
-- 创建用户,% 表示可远程访问(建议配合防火墙控制 IP 白名单)
CREATE USER 'microservice_user'@'%' IDENTIFIED BY 'strongpassword';-- 授予所有库所有表的所有权限(仅限开发或测试环境)
GRANT ALL PRIVILEGES ON *.* TO 'microservice_user'@'%';-- 使权限变更生效
FLUSH PRIVILEGES;
✅ 提示:在生产环境中,请仅授予最小必要权限,例如:
GRANT SELECT, INSERT, UPDATE, DELETE ON `user_service_db`.* TO 'microservice_user'@'%';
3. 防止常见连接报错的参数配置
在开发和部署过程中,常会遇到如下连接报错或行为异常,可通过以下参数配置优化:
报错 / 问题 | 建议设置 |
---|---|
Too many connections | max_connections = 200 (根据并发需求调整) |
SQL 模式太严格(如禁止 null) | sql_mode 设为简化版本 |
默认密码插件导致连接失败 | 使用 caching_sha2_password 替代旧密码插件 |
示例配置(添加到 my.cnf
中):
[mysqld]
max_connections = 200
sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
default_authentication_plugin = caching_sha2_password
重启 MySQL 生效:
sudo systemctl restart mysql
✅ 最后检查:确认配置生效
SHOW VARIABLES WHERE Variable_name IN ('character_set_server', 'max_connections', 'sql_mode');
示例输出:
character_set_server | utf8mb4
max_connections | 200
sql_mode | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION
二. 微服务架构核心概念:服务拆分
1. 电商平台案例引入
以京东为例拆解核心功能模块
假设我们正在构建一个类似京东的电商平台,其核心业务功能大致可划分为以下模块:
功能模块 | 说明 |
---|---|
用户服务 | 注册、登录、实名认证、账户管理等 |
商品服务 | 商品发布、上下架、分类、详情、价格、库存等 |
搜索服务 | 支持关键词搜索、筛选排序、热搜推荐、搜索联想等 |
订单服务 | 创建订单、订单状态流转、取消订单、售后申请等 |
支付服务 | 支持多种支付方式(如微信、支付宝、银行卡),支付回调等 |
评论服务 | 用户对商品的评价内容管理 |
物流服务 | 订单配送进度查询、快递单号追踪等 |
营销服务 | 优惠券、满减、积分、秒杀、推荐算法等 |
传统单体架构的痛点
在早期开发中,这些模块可能会被统一封装在一个大型单体系统中,例如:
电商系统(单体)
├── user.controller.java
├── order.controller.java
├── product.service.java
├── search.utils.java
├── 全部模块部署在同一个 WAR 包中
虽然开发初期看起来“方便快速”,但随着业务增长,很快会暴露出一系列问题:
痛点 | 描述 |
---|---|
代码臃肿 | 所有业务逻辑集中在一个项目中,类数量剧增,模块边界模糊 |
维护困难 | 一个小功能的修改可能波及大量模块,容易产生 Bug |
部署频繁冲突 | 任一模块改动都需整体打包部署,无法独立发布 |
扩展受限 | 各模块资源争用严重,难以实现弹性伸缩(如高并发搜索拖慢下单功能) |
技术架构难以演进 | 不同模块对技术栈或性能的要求不同,单体架构下难以引入异构技术 |
✅ 为何要拆分成微服务?
通过 服务拆分(Service Decomposition),我们将单体应用中不同领域的业务逻辑,按照职责边界清晰的服务进行重构,每个服务成为独立运行、部署、维护的单元。
一、业务驱动:应对复杂业务的必然选择
1. 业务复杂度失控
- 场景:传统单体架构中,电商平台的用户、订单、商品、支付等功能耦合在一个代码库中,代码量超百万行,新增 “会员积分” 功能需修改用户、订单、营销等多个模块,开发周期从 2 周延长至 1 个月。
- 微服务价值:
- 职责隔离:将会员积分独立为 “积分服务”,仅负责积分规则计算与存储,其他服务通过 API 调用,开发周期缩短至 3 天。
- 试错成本低:新业务(如社交分享功能)可独立部署为 “社交服务”,失败时直接下线,不影响核心交易流程。
2. 业务快速迭代需求
- 场景:互联网业务需频繁发布新功能(如电商大促期间每日上线促销活动),单体架构每次发布需全量测试,导致凌晨发布窗口延长至 4 小时,影响用户体验。
- 微服务价值:
- 独立发布:促销相关的 “营销服务” 可每日凌晨快速更新,其他服务(如用户、支付)保持稳定运行。
- 灰度发布:新功能先在 10% 的用户流量中验证,问题修复不影响全量用户。
二、技术驱动:突破单体架构的技术瓶颈
1. 技术栈僵化与创新受限
- 场景:传统单体架构使用老旧技术栈(如 Spring Framework 4.x + MyBatis 2.x),难以引入新框架(如 Spring Boot 3.x + Kotlin),技术债务累积导致维护成本激增。
- 微服务价值:
- 技术异构:新服务可独立采用新技术(如用 Go 重构支付服务,用 Python 开发数据分析服务),老服务逐步迁移,避免 “颠覆性重构” 风险。
- 性能优化针对性:高并发的 “商品搜索服务” 可采用 Elasticsearch+Reactive 编程模型,低延迟的 “订单服务” 保留传统数据库 + 同步模型。
2. 扩展性与稳定性瓶颈
- 场景:电商大促期间,商品详情页流量激增 500%,但单体架构无法单独扩容 “商品查询” 功能,只能整体升级服务器,成本增加 3 倍且响应时间仍超时。
- 微服务价值:
- 按需扩容:仅对 “商品服务” 增加 10 个实例,其他服务(如用户、物流)维持原有资源,成本降低 60% 且响应时间从 500ms 降至 100ms。
- 故障隔离:商品服务因缓存击穿导致内存溢出时,自动重启该服务实例,用户、订单等其他服务正常运行,系统可用性从 99% 提升至 99.9%。
三、团队驱动:匹配敏捷开发与组织架构
1. 团队协作效率低下
- 场景:千人开发团队共同维护单体代码库,分支冲突日均超 100 次,代码评审耗时从 2 小时延长至 8 小时,需求交付周期从 2 周延长至 1 个月。
- 微服务价值:
- 康威定律适配:按服务拆分为独立团队(如用户团队、订单团队),每个团队负责 1-2 个服务,沟通成本降低 70%,分支冲突减少 90%。
- 自治交付流程:每个团队拥有独立的 CI/CD 流水线,可自主决定发布节奏,需求平均交付周期缩短至 3 天。
2. 技术责任清晰化
- 场景:单体架构中,“用户登录缓慢” 问题需跨多个模块排查(如认证模块、数据库、缓存),定位问题耗时 2 天,责任归属不明确。
- 微服务价值:
- 责任边界清晰:登录问题直接归属 “用户服务” 团队,该团队可独立排查服务代码、数据库索引、接口性能,问题定位时间缩短至 2 小时。
- 技术所有权:团队对所负责的服务技术选型、架构设计完全负责,提升技术决策效率与团队成就感。
四、微服务的核心优势总结
维度 | 单体架构痛点 | 微服务解决方案 |
---|---|---|
复杂度管理 | 模块耦合导致 “牵一发而动全身” | 单一职责拆分,每个服务逻辑独立 |
扩展性 | 无法局部扩容,资源浪费严重 | 按需扩展单个服务,支持弹性伸缩 |
技术演进 | 技术栈固化,难以引入新技术 | 支持异构技术,老服务逐步平滑迁移 |
团队效率 | 协作成本高,需求交付周期长 | 按服务拆分为小团队,敏捷开发更高效 |
稳定性 | 单点故障导致全局不可用 | 服务自治与故障隔离,局部失败不扩散 |
五、何时不适合拆分微服务?
微服务并非银弹,以下场景需谨慎考虑:
- 简单小型项目:如内部工具、单业务应用,拆分成本可能高于收益。
- 强事务一致性场景:如金融交易核心系统,跨服务事务实现复杂(需引入 TCC/Saga 等模式)。
- 团队规模小或技术能力不足:缺乏 DevOps 工具链与分布式系统经验,可能导致 “服务爆炸” 与运维混乱。
2. 服务拆分原则与实践
微服务架构的关键之一在于 合理拆分服务边界,否则将陷入“伪微服务”陷阱——系统虽然看似模块化,实则高度耦合、维护困难。因此,遵循科学的服务拆分原则,是构建稳定微服务体系的前提。
1. 单一职责原则:每个微服务专注一个业务领域
-
每个微服务应对应一个清晰的业务边界,避免“大而全”或“多而碎”。
-
拆分参考维度:
-
业务领域模型(DDD):如用户、订单、库存、营销
-
组织结构:一个团队负责一个服务,便于治理与协作
-
生命周期差异:变更频率不同的模块应分开(如搜索 vs 支付)
-
✅ 示例:
-
UserService
: 只处理用户注册、认证、账户管理 -
OrderService
: 只负责下单、支付流程、订单状态流转
2. 服务自治:独立开发、测试、部署
-
每个服务应具备“自给自足”的能力,包括:
-
独立的数据库 Schema(避免跨库 JOIN)
-
独立的配置文件与依赖管理(Spring Boot 配置分离)
-
独立部署与版本管理(如通过 Docker、K8s 部署)
-
🎯 目标:不影响其他服务的前提下,任何服务都能独立上线或回滚。
3. 单向依赖:避免循环依赖,简化调用关系
-
微服务之间应该建立清晰的调用链条,尽量避免双向调用(A ↔ B)。
-
推荐设计成 单向依赖(A → B) 或通过事件驱动进行解耦。
📌 错误示例:
用户服务 A → 订单服务 B → 用户服务 A ❌ 形成循环依赖,难以维护
✅ 推荐方式:
-
使用消息队列或事件总线解耦,例如订单服务发布“订单已创建”事件,用户服务异步监听并更新积分。
依赖关系图示意:
正确设计(单向):
A → B → C错误设计(循环):
A → B → A
4. 业界经验:合适优于先进,避免过度设计
-
微服务不是越小越好,过度拆分会导致:
-
调用链复杂、调试困难
-
网络通信成本上升
-
运维压力加大(每个服务都要部署、监控)
-
🎯 经验总结:
-
不盲目追求“微粒度”,而应按需拆分,确保每个服务能被有效拥有、维护、监控。
-
拆分标准应结合业务成熟度、团队能力与组织架构。
“架构的第一原则,不是先进,而是合适。”
3. 拆分示例:订单与商品服务
在微服务架构中,“订单服务”与“商品服务”是电商平台中的核心组成部分。二者职责明确、调用频率高,但业务边界清晰,适合做为微服务拆分的典型案例。
1. 订单服务职责:专注订单生命周期管理
-
处理用户下单请求
-
管理订单状态(如:已创建、已支付、已发货、已完成、已取消)
-
与商品服务交互,引用商品 ID,但不直接保存商品详情
-
与支付服务、物流服务等后续模块协作
✅ 示例:
{"orderId": "ORD2024060001","userId": 10001,"productId": 20009,"quantity": 2,"status": "PAID"
}
2. 商品服务职责:专注商品信息维护与查询
-
管理商品的基本信息、价格、库存
-
支持商品详情查询、分类管理、上下架操作
-
对外提供商品详情接口供订单服务、搜索服务等调用
✅ 示例:
{"productId": 20009,"name": "机械键盘","price": 399.00,"stock": 120,"status": "AVAILABLE"
}
3. 数据库拆分:cloud_order 与 cloud_product 独立建表
按照“服务自治”原则,每个服务拥有自己的数据库,分别命名为:
-
cloud_order
(订单服务) -
cloud_product
(商品服务)
📦 订单服务建表语句(cloud_order.orders
)
-- 建库
create database if not exists cloud_order charset utf8mb4;
-- 订单表
DROP TABLE IF EXISTS order;
CREATE TABLE order_detail (`id` INT NOT NULL AUTO_INCREMENT COMMENT '订单id',`user_id` BIGINT ( 20 ) NOT NULL COMMENT '⽤⼾ID',`product_id` BIGINT ( 20 ) NULL COMMENT '产品id',`num` INT ( 10 ) NULL DEFAULT 0 COMMENT '下单数量',`price` BIGINT ( 20 ) NOT NULL COMMENT '实付款',`delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '订单表';创建数据
INSERT INTO order_detail (user_id, product_id, num, price, delete_flag, create_time, update_time)
VALUES-- 用户1001的有效订单(delete_flag=0)(1001, 2001, 1, 9800, 0, '2024-01-01 10:00:00', '2024-01-01 10:00:00'), -- 购买T恤1件,实付98元(1001, 2003, 2, 24000, 0, '2024-01-03 14:30:00', '2024-01-03 14:30:00'), -- 购买短裤2件,实付240元(单价120元)-- 用户1002的有效订单(delete_flag=0)(1002, 2002, 3, 9000, 0, '2024-01-02 09:15:00', '2024-01-02 09:15:00'), -- 购买短袖3件,实付90元(单价30元)(1002, 2005, 1, 9800, 0, '2024-01-04 16:45:00', '2024-01-04 16:45:00'), -- 购买马甲1件,实付98元-- 用户1003的已删除订单(delete_flag=1)(1003, 2004, 1, 5800, 1, '2024-01-05 11:20:00', '2024-01-05 15:00:00'), -- 购买卫衣1件,实付58元,已删除(1003, 2006, 2, 18800, 1, '2024-01-06 13:00:00', '2024-01-06 17:30:00'), -- 购买羽绒服2件,实付188元,已删除-- 批量测试数据(模拟大促订单)(1004, 2007, 5, 15000, 0, '2024-01-11 08:30:00', '2024-01-11 08:30:00'), -- 冲锋衣5件,实付150元(1005, 2008, 10, 4400, 0, '2024-01-12 14:10:00', '2024-01-12 14:10:00'), -- 袜子10件,实付44元(5双装单价39元,此处模拟优惠后价格)(1001, 2009, 2, 11600, 0, '2024-01-13 11:00:00', '2024-01-13 11:00:00'), -- 鞋子2双,实付116元(1002, 2010, 1, 9800, 0, '2024-01-14 15:40:00', '2024-01-14 15:40:00'); -- 毛衣1件,实付98元
📦 商品服务建表语句(cloud_product.products
)
create database if not exists cloud_product charset utf8mb4;
-- 产品表
DROP TABLE IF EXISTS product;
CREATE TABLE product_detail (`id` INT NOT NULL AUTO_INCREMENT COMMENT '产品id',`product_name` varchar ( 128 ) NULL COMMENT '产品名称',`product_price` BIGINT ( 20 ) NOT NULL COMMENT '产品价格',`state` TINYINT ( 4 ) NULL DEFAULT 0 COMMENT '产品状态 0-有效 1-下架',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( id )) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '产品表';数据初始化
INSERT INTO product_detail (product_name, product_price, state, create_time, update_time)
VALUES-- 有效商品(state=0)('纯棉圆领T恤', 9800, 0, '2023-12-01 10:00:00', '2023-12-01 10:00:00'),('冰丝短袖衬衫', 15800, 0, '2023-12-02 14:30:00', '2023-12-05 09:00:00'),('宽松牛仔短裤', 12800, 0, '2023-12-03 16:15:00', '2023-12-03 16:15:00'),('连帽卫衣', 19800, 0, '2023-12-04 08:45:00', '2023-12-04 08:45:00'),('加绒休闲裤', 22800, 0, '2023-12-05 11:20:00', '2023-12-05 11:20:00'),('中长款羽绒服', 89800, 0, '2023-12-06 13:00:00', '2023-12-06 13:00:00'),('防水冲锋衣', 59800, 0, '2023-12-07 15:40:00', '2023-12-07 15:40:00'),('运动老爹鞋', 39800, 0, '2023-12-08 09:30:00', '2023-12-08 09:30:00'),('纯棉袜子(5双装)', 3900, 0, '2023-12-09 14:10:00', '2023-12-09 14:10:00'),('羊毛围巾', 15800, 0, '2023-12-10 11:00:00', '2023-12-10 11:00:00'),-- 下架商品(state=1)('旧款打底衫', 5800, 1, '2023-11-25 09:00:00', '2023-12-01 00:00:00'),('断码运动鞋', 19900, 1, '2023-11-30 14:20:00', '2023-12-02 00:00:00'),('季节性凉鞋', 8800, 1, '2023-11-28 16:30:00', '2023-12-03 00:00:00'),('清仓羽绒服', 49800, 1, '2023-12-01 10:00:00', '2023-12-05 00:00:00'),('样品毛衣', 12800, 1, '2023-12-02 11:15:00', '2023-12-06 00:00:00');
四、Maven 父子工程搭建
1. 父工程配置
一、父工程核心作用:统一依赖管理
1. 避免依赖冲突
通过父工程集中定义依赖版本,确保子工程使用一致的库版本,避免出现 “同一个依赖不同子工程版本不一致” 导致的类冲突(如 Spring Boot Starter 与 Spring Cloud 组件版本不兼容)。
2. 简化子工程配置
子工程无需重复声明版本号,直接继承父工程的依赖配置,减少冗余代码,提升维护效率。例如:
- 父工程定义
spring-boot.version=3.1.6
,子工程只需声明spring-boot-starter-web
依赖,无需指定版本。
3. 技术栈统一管理
集中控制项目的技术栈(如 JDK 版本、构建插件、基础框架),确保团队所有成员使用一致的开发环境。
二、pom.xml
关键配置解析
1. dependencyManagement
vs dependencies
配置项 | dependencyManagement | dependencies |
---|---|---|
功能定位 | 声明依赖版本(但不实际引入) | 实际引入依赖到项目 |
子工程继承行为 | 子工程需显式声明依赖才能使用 | 子工程自动继承并包含依赖 |
版本覆盖规则 | 子工程可覆盖声明的版本 | 子工程需排除父依赖后再引入新版本 |
使用场景 | 统一管理依赖版本(如 Spring Boot) | 明确需要引入的依赖(如 Lombok) |
-
误用
dependencyManagement
- 错误做法:在父工程
dependencyManagement
中声明所有依赖,但子工程忘记显式声明,导致依赖未引入。 - 正确做法:仅在
dependencyManagement
中声明版本,在dependencies
中实际引入依赖。
- 错误做法:在父工程
-
忽略依赖传递性
- 问题:父工程引入的依赖通过传递性影响子工程,但未显式声明,导致调试困难。
- 检查方法:使用
mvn dependency:tree
命令查看依赖树,确认依赖来源。
-
版本冲突排查
- 症状:编译时报类找不到或版本不兼容错误。
三 、工程创建
创建⽗⼯程 : 创建⼀个空的Maven项⽬,删除所有代码,只保留pom.xml
⽬录结构:
2. 完善pom⽂件
使⽤properties来进⾏版本号的统⼀管理,使⽤dependencyManagement来管理依赖,声明⽗⼯程的打 包⽅式为pom
<?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>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version><modules><module>order-service</module><module>product-service</module></modules><packaging>pom</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><java.version>17</java.version><mybatis.version>3.0.3</mybatis.version><mysql.version>8.0.33</mysql.version><spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.version><spring-cloud.version>2022.0.3</spring-cloud.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><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><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.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>${mybatis.version}</version><scope>test</scope></dependency></dependencies></dependencyManagement></project>
3. 创建⼦项⽬-订单服务
声明项⽬依赖和项⽬构建插件
<?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>spring-cloud-demo</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>order-service</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency> <groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-bootstrap --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>3.0.3</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency></dependencies><profiles><profile><id>dev</id><properties><profile.name>dev</profile.name></properties></profile><profile><id>prod</id><properties><profile.name>prod</profile.name></properties></profile></profiles><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>**/**</include></includes></resource></resources></build></project>
4 创建⼦项⽬-商品服务
声明项⽬依赖和项⽬构建插件
<?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>spring-cloud-demo</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>product-service</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><dependency> <groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- SpringCloud 2020.*之后版本需要引⼊bootstrap--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-bootstrap --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>3.0.3</version></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency></dependencies><profiles><profile><id>dev</id><properties><profile.name>dev</profile.name></properties></profile><profile><id>prod</id><properties><profile.name>prod</profile.name></properties></profile></profiles><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins><resources><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>**/**</include></includes></resource></resources></build></project>
5 完善订单服务
完善启动类,配置⽂件
package com.bite.order;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class, args);}
}
配置⽂件 application.yml
server:port: 8080
spring:application:name: order-serviceprofiles:active: @profile.name@datasource:url: jdbc:mysql://127.0.0.1:3306/cloud_order?characterEncoding=utf8&useSSL=falseusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver
业务代码
实体类
package com.bite.order.model;import lombok.Data;import java.util.Date;@Data
public class OrderInfo {private Integer id;private Integer userId;private Integer productId;private Integer num;private Integer price;private Integer deleteFlag;private Date createTime;private Date updateTime;private ProductInfo productInfo;
}
Controller
package com.bite.order.controller;import com.bite.order.model.OrderInfo;
import com.bite.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RequestMapping("/order")
@RestController
public class OrderController {@Autowiredprivate OrderService orderService;@RequestMapping("/{orderId}")public OrderInfo getOrderById(@PathVariable("orderId") Integer orderId){return orderService.selectOrderById(orderId);}
}
Service
import com.bite.order.mapper.OrderMapper;
import com.bite.order.model.OrderInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;
public OrderInfo selectOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectOrderById(orderId);return orderInfo;}
}
Mapper
import com.bite.order.model.OrderInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface OrderMapper {@Select("select * from order_detail where id=#{orderId}")OrderInfo selectOrderById(Integer orderId);
}
测试
访问url:http://127.0.0.1:8080/order/1
⻚⾯正常返回结果:
6 完善商品服务
与上面 完善订单服务 的代码差不多一样 ,可以对照这写,要注意的是端口号不能设一样的,数据库要改一下,实体类的表对照着商品的数据库写,其他的没啥不一样了,这里我就不多写商品服务的代码了
结语:在实践中深化对微服务架构的理解
至此,我们完成了从 Spring Cloud 开发环境搭建到微服务项目实战的全流程探索。这一路径不仅是技术栈的实践,更是对分布式架构思维的系统性训练。以下从核心收获、实践建议和未来方向三个维度,为本次学习之旅做阶段性总结。
一、核心收获:从理论到代码的架构思维升级
-
微服务设计原则的落地
通过电商案例的服务拆分(订单 / 商品服务),我们深入理解了单一职责(每个服务专注独立业务)、服务自治(独立数据库与部署)、单向依赖(避免循环调用)的实践逻辑。例如,订单服务仅通过商品 ID 关联商品服务接口,而非直接操作数据库,确保了服务边界清晰。 -
Maven 父子工程的依赖管理哲学
dependencyManagement
如同 “中央控制室”,统一管理 Spring Boot、Spring Cloud 等核心组件版本,避免子工程依赖冲突。dependencies
则是 “执行器”,按需引入 Lombok、MyBatis 等具体依赖,实现 “版本中央控制,依赖按需加载” 的高效模式。
-
跨服务调用的基础实现
通过 RestTemplate 完成订单服务与商品服务的联动,我们掌握了微服务间通信的基本范式:基于 HTTP 协议的同步调用、数据格式转换(如 JSON 序列化)和接口契约管理(如 URL 路径规范)。
二、实践建议:避坑指南与效率提升
-
开发环境的细节把控
- JDK 版本锁定:务必使用 JDK17+,避免因版本过低导致 Spring Boot 3.x 特性无法使用(如虚拟线程)。
- 数据库字符集统一:建表时指定
utf8mb4
字符集,确保对 emoji 等特殊字符的支持,避免乱码问题。
-
代码结构的规范化
- 分层清晰性:严格遵循 “Controller→Service→Mapper” 分层,避免业务逻辑泄漏到 Controller 层。例如,订单服务的
OrderController
仅负责接收请求和返回结果,具体业务逻辑封装在OrderService
中。 - 实体类轻量化:避免在实体类中添加非必要字段(如冗余的关联数据),保持 POJO 的纯粹性。
- 分层清晰性:严格遵循 “Controller→Service→Mapper” 分层,避免业务逻辑泄漏到 Controller 层。例如,订单服务的
-
测试与验证的系统性
- 单服务测试先行:使用 Postman 或 Swagger 验证单个接口(如
/product/{id}
)的正确性,确保返回数据格式与预期一致。 - 跨服务链路测试:通过组合调用(如订单查询触发商品信息获取),验证数据整合逻辑的可靠性,例如检查订单结果中是否正确嵌套商品名称和价格。
- 单服务测试先行:使用 Postman 或 Swagger 验证单个接口(如
三、未来方向:从基础到进阶的技术图谱
当前项目仅实现了微服务架构的 “Hello World” 级演示,要应对真实生产环境,还需深入探索 Spring Cloud 的核心组件:
-
服务治理:从静态到动态的服务管理
- 服务注册与发现:引入 Nacos 或 Eureka,将订单 / 商品服务注册到注册中心,避免硬编码 IP 和端口(如用
product-service
服务名替代127.0.0.1:9090
)。 - 负载均衡:通过 Ribbon 或 Spring Cloud LoadBalancer 实现商品服务多实例间的请求分发,提升系统吞吐量。
- 服务注册与发现:引入 Nacos 或 Eureka,将订单 / 商品服务注册到注册中心,避免硬编码 IP 和端口(如用
-
分布式基础设施:应对高并发与复杂性
- 熔断与降级:使用 Hystrix 或 Resilience4j 防止服务雪崩,例如当商品服务不可用时,订单服务可返回缓存数据或友好提示。
- 配置中心:通过 Spring Cloud Config 统一管理多环境配置(如开发 / 测试 / 生产环境的数据库 URL),避免敏感信息硬编码。
-
观测性与可维护性
- 分布式链路追踪:集成 Sleuth+Zipkin,记录跨服务调用链路(订单服务→商品服务),快速定位性能瓶颈或故障点。
- 日志聚合:使用 ELK Stack(Elasticsearch+Logstash+Kibana)集中管理各服务日志,支持按关键字、时间范围查询。
四、写在最后:微服务的本质是 “平衡的艺术”
微服务架构并非追求 “绝对的拆分” 或 “最先进的技术”,而是在业务复杂度、团队能力、系统稳定性之间寻找动态平衡点:
- 初期:采用粗粒度拆分(如将用户与会员功能合并),快速验证业务逻辑;
- 中期:随着流量增长,逐步细化服务(如拆分为用户服务、会员积分服务),引入负载均衡和熔断机制;
- 长期:通过容器化(Docker+K8s)和云原生技术,实现服务的弹性扩缩容与自动化运维。
技术的价值始终在于解决实际问题。希望通过本次实战,你不仅掌握了 Spring Cloud 的基础开发流程,更能建立 “从问题出发设计架构” 的思维 —— 这正是应对未来技术挑战的核心能力。
下一步,让我们带着这些经验,深入探索 Spring Cloud 的服务注册与发现机制,开启真正的分布式系统之旅!
欢迎在评论区分享你的实践心得或遇到的问题,我们共同成长! 🌟
下期预告:
远程调用实现:RestTemplate 讲解
项目问题与 Spring Cloud 解决方案前瞻
总结与延伸学习