basics 阶段定了边界与通信;practice 从可运行的工程骨架开始。版本对齐(Boot + Cloud BOM)、模块分层与 Profile 约定若在一开始做错,后续注册发现、Feign、Kafka 会在依赖冲突与配置漂移上反复踩坑。
application.yml、Profile 与本地启动顺序spring-cloud-dependencies 统一管理,子模块勿手写版本号。本课栈:Java 21 LTS、Spring Boot 3.5.x、Spring Cloud 2025.0.x(2025.1 发布列车)。Spring Cloud 采用发布列车(Release Train)命名:2025.0.1 与 Boot 3.5 在官方兼容矩阵中配对,子项目通过 BOM import 继承版本。
<!-- shopflow/pom.xml 片段 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.0</version>
</parent>
<properties>
<java.version>21</java.version>
<spring-cloud.version>2025.0.1</spring-cloud.version>
</properties>
<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>
</dependencies>
</dependencyManagement>
openfeign 版本spring-cloud.version<version>.mvn/jvm.config 或 CI 固定 JDK 21可以跑单个 REST 服务,但 ShopFlow 实战依赖注册发现、Gateway、OpenFeign。本章仍引入 Cloud BOM,以便下一章直接加 spring-cloud-starter-netflix-eureka-client 而无需改版本矩阵。
将 领域建模、边界上下文与 API 契约 中的 ShopFlow 三上下文落到 Maven 模块:每个上下文至少 api + service,共享能力放入 common。这与 模块化单体 的分模块思路一致,只是 service 模块将独立进程部署为 微服务。
flowchart TB
subgraph parent[shopflow-parent]
C[shopflow-common]
OA[order-api]
OS[order-service]
IA[inventory-api]
IS[inventory-service]
PA[payment-api]
PS[payment-service]
end
OS --> OA
OS --> C
IS --> IA
IS --> C
PS --> PA
PS --> C
service 依赖对应 api + common;service 之间禁止直接依赖对方 implementation,跨上下文走 HTTP/事件(见 basics 契约)。
| 模块后缀 | 职责 | ShopFlow 示例 |
|---|---|---|
| -api | DTO、Feign 接口、OpenAPI 生成物;无 Spring 运行时 | CreateOrderRequest、OrderApi |
| -service | @SpringBootApplication、Controller、领域逻辑、持久化 |
order-service 端口 8081 |
| common | 错误码枚举、JSON 工具、日志 MDC 助手 | ShopFlowErrorCodes |
<!-- shopflow-order-service/pom.xml -->
<dependencies>
<dependency>
<groupId>com.shopflow</groupId>
<artifactId>shopflow-order-api</artifactId>
</dependency>
<dependency>
<groupId>com.shopflow</groupId>
<artifactId>shopflow-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
多服务本地联调时,端口、数据源、日志级别必须可切换且可预测。ShopFlow 约定:
application.yml 放共享默认(应用名、Actuator 暴露端点)。application-local.yml 本地 H2/端口;application-docker.yml 供 Compose(见 practice-02)。spring.profiles.active=local(IDE Run Configuration 或环境变量)。.env / 环境变量占位(生产走 Config Server,见 advanced 章)。spring:
application:
name: order-service
management:
endpoints:
web:
exposure:
include: health,info
endpoint:
health:
show-details: when_authorized
server:
port: 8081
logging:
level:
com.shopflow: DEBUG
同一 artifact 要在本地、CI、容器中使用不同端口与环境;外部化后只需改 Profile 或环境变量,避免重新编译。也与 通信模式 中「契约稳定、部署可变」一致。
推荐 monorepo 根目录 shopflow/,与课程 Demo 对齐。首章只需能启动 order-service 并访问健康检查;inventory / payment 可先留空模块占位。
shopflow/
├── pom.xml # 父 POM + BOM
├── shopflow-common/
├── shopflow-order-api/
├── shopflow-order-service/
│ └── src/main/java/.../OrderServiceApplication.java
├── shopflow-inventory-api/
├── shopflow-inventory-service/
├── shopflow-payment-api/
└── shopflow-payment-service/
java -version 为 21;根目录 mvn -q -DskipTests install 编译全模块。shopflow-order-service,mvn spring-boot:run -Dspring-boot.run.profiles=local。http://localhost:8081/actuator/health,期望 {"status":"UP"}。OrderServiceApplication,VM options 加 -Dspring.profiles.active=local。practice-02 将先启动注册中心,再启动 order / inventory 并注册;本章无需 Eureka,但请保持应用名 spring.application.name 与模块名一致,便于后续服务发现。
Spring Boot Actuator 提供生产就绪端点。本地与 K8s 探针都依赖 /actuator/health;统一 JSON 日志则便于后续接入 ELK 与 traceId(可观测性 章展开)。
env、beans 等敏感端点;生产用 Spring Security 或网络策略。<!-- shopflow-common/src/main/resources/logback-spring.xml 片段 -->
<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeMdcKeyName>traceId</includeMdcKeyName>
<customFields>{"service":"${spring.application.name:-unknown}"}</customFields>
</encoder>
</appender>
本章在 common 中引入 logstash-logback-encoder,各 service 自动继承;日志行含 service、预留 traceId MDC 字段,与 Cloud 可观测组件 后续对齐。
| 路径 | 用途 |
|---|---|
/actuator/health | 存活/就绪(K8s 探针) |
/actuator/info | 构建版本、Git 信息(可选) |
/actuator/metrics | Micrometer 指标(advanced 章) |
每条对应上一节 h3,practice 阶段起步复述。
spring-cloud-dependencies 2025.0.x BOM;JDK 21;子模块不写 Cloud 组件版本。application.yml + Profile(local/docker);端口与敏感项外部化。spring-boot:run → 验证 /actuator/health。过关清单(勾选会保存在本浏览器)
0 / 5 已勾选
下一步:完成 Demo 与测验;继续 服务注册发现与 API 网关,把 order / inventory 注册到 Eureka 并经由 Gateway 统一入口。
在本地跑通 order-service,完成父 POM、多模块、Profile 与 Actuator 命令级验收。
shopflow/pom.xml 含 spring-cloud.version 与 BOM import;在子模块手写 <version> 观察冲突后改回。application-local.yml 端口,mvn spring-boot:run -Dspring-boot.run.profiles=local,curl -s localhost:8081/actuator/health 期望 UP。"service":"order-service"。端口写进 Java 静态字段且无 application-local.yml。两处应改回外部化的位置?违反哪条 Profile 约定?
删除 Java 硬编码;在 application-local.yml 写 server.port,默认 application.yml 放共享项。违反「环境差异外部化、同一 artifact 多环境复用」。
子模块 pom 中 OpenFeign 写死 4.0.0,与 BOM 2025.0.1 并存。应删哪段?保留有何风险?
删除子模块依赖上的 <version>4.0.0</version>,由 BOM 管理。保留可能导致与 Boot 3.5 矩阵不兼容、集成测试通过但生产 classpath 冲突。
目录:demos/practice-01-spring-cloud-bootstrap-lab/。验收:mvn install 成功 + health 为 UP + 改端口后仍可达。