已完成Spring Boot 3.5 与 Spring Cloud 脚手架

约 35 分钟 · 阶段:Java 微服务栈实战 · 能力:搭建 ShopFlow 多模块父工程并本地启动首个服务

为什么要学本章

basics 阶段定了边界与通信;practice 从可运行的工程骨架开始。版本对齐(Boot + Cloud BOM)、模块分层与 Profile 约定若在一开始做错,后续注册发现、Feign、Kafka 会在依赖冲突与配置漂移上反复踩坑。

学完你能
  • 用 JDK 21 + Maven 导入 Spring Cloud BOM,与 Spring Boot 3.5 对齐
  • 按 api / service / common 拆分 ShopFlow 多模块工程
  • 约定 application.yml、Profile 与本地启动顺序
  • 启用 Actuator 健康检查与统一 JSON 日志格式
本章先记住 3 件事
  • BOM 管版本:Cloud 组件版本由 spring-cloud-dependencies 统一管理,子模块勿手写版本号。
  • 模块边界:api 放 DTO/契约,service 可运行,common 放跨服务工具;与 限界上下文 一一对应。
  • 先单体模块、后拆进程:本章先跑通 order-service;全链路注册发现见 服务注册发现与 API 网关。

JDK 21、Maven BOM 与 Spring Cloud 2025 对齐

本课栈: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 继承版本。

父 POM:Boot 父 + Cloud BOM

xml
<!-- 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>
版本散落
  • 各 service 的 pom 手写 openfeign 版本
  • Boot 3.4 与 Cloud 2025 混用
  • CI 与本地 JDK 不一致(仍用 17)
BOM 统一
  • 父 POM 一处定义 spring-cloud.version
  • 子模块依赖不写 <version>
  • .mvn/jvm.config 或 CI 固定 JDK 21
FAQ:能否只用 Spring Boot、暂不引 Cloud?

可以跑单个 REST 服务,但 ShopFlow 实战依赖注册发现、Gateway、OpenFeign。本章仍引入 Cloud BOM,以便下一章直接加 spring-cloud-starter-netflix-eureka-client 而无需改版本矩阵。

多模块工程:api / service / common 分层

将 领域建模、边界上下文与 API 契约 中的 ShopFlow 三上下文落到 Maven 模块:每个上下文至少 api + service,共享能力放入 common。这与 模块化单体 的分模块思路一致,只是 service 模块将独立进程部署为 微服务。

ShopFlow 多模块拓扑(本章目标范围)
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

order-service 最小依赖

xml
<!-- 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>

配置外部化与 Profile 约定

多服务本地联调时,端口、数据源、日志级别必须可切换且可预测。ShopFlow 约定:

  • 默认:application.yml 放共享默认(应用名、Actuator 暴露端点)。
  • 环境:application-local.yml 本地 H2/端口;application-docker.yml 供 Compose(见 practice-02)。
  • 激活:spring.profiles.active=local(IDE Run Configuration 或环境变量)。
  • 敏感项:不进 Git;用 .env / 环境变量占位(生产走 Config Server,见 advanced 章)。
yaml
spring:
  application:
    name: order-service
management:
  endpoints:
    web:
      exposure:
        include: health,info
  endpoint:
    health:
      show-details: when_authorized
yaml
server:
  port: 8081
logging:
  level:
    com.shopflow: DEBUG
先想 10 秒:为何不把 8081 端口写死在 Java 代码里?

同一 artifact 要在本地、CI、容器中使用不同端口与环境;外部化后只需改 Profile 或环境变量,避免重新编译。也与 通信模式 中「契约稳定、部署可变」一致。

ShopFlow 仓库结构与本地启动顺序

推荐 monorepo 根目录 shopflow/,与课程 Demo 对齐。首章只需能启动 order-service 并访问健康检查;inventory / payment 可先留空模块占位。

目录树(精简)

bash
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/

本地启动顺序(本章)

  1. 确认 java -version 为 21;根目录 mvn -q -DskipTests install 编译全模块。
  2. 进入 shopflow-order-service,mvn spring-boot:run -Dspring-boot.run.profiles=local。
  3. 访问 http://localhost:8081/actuator/health,期望 {"status":"UP"}。
  4. (可选)用 IDE 运行 OrderServiceApplication,VM options 加 -Dspring.profiles.active=local。
与后续章节衔接

practice-02 将先启动注册中心,再启动 order / inventory 并注册;本章无需 Eureka,但请保持应用名 spring.application.name 与模块名一致,便于后续服务发现。

健康检查 Actuator 与统一日志格式

Spring Boot Actuator 提供生产就绪端点。本地与 K8s 探针都依赖 /actuator/health;统一 JSON 日志则便于后续接入 ELK 与 traceId(可观测性 章展开)。

健康检查分组(入门)

  • liveness:进程是否存活(默认 health 即可)。
  • readiness:是否可接流量(后续加 DB、注册中心检查)。
  • 勿对外暴露 env、beans 等敏感端点;生产用 Spring Security 或网络策略。

统一 JSON 日志(Logback)

xml
<!-- 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 端点速查
路径用途
/actuator/health存活/就绪(K8s 探针)
/actuator/info构建版本、Git 信息(可选)
/actuator/metricsMicrometer 指标(advanced 章)

本章结论

每条对应上一节 h3,practice 阶段起步复述。

  • 版本对齐:父 POM 用 Boot 3.5 + spring-cloud-dependencies 2025.0.x BOM;JDK 21;子模块不写 Cloud 组件版本。
  • 模块分层:api / service / common 对应限界上下文;service 可独立启动,跨上下文只走 API/事件。
  • 配置约定:application.yml + Profile(local/docker);端口与敏感项外部化。
  • 启动顺序:根目录 install → 单服务 spring-boot:run → 验证 /actuator/health。
  • 可运维基线:Actuator health + 统一 JSON 日志,为注册发现与可观测性铺路。

复习与自检

过关清单(勾选会保存在本浏览器)

0 / 5 已勾选

下一步:完成 Demo 与测验;继续 服务注册发现与 API 网关,把 order / inventory 注册到 Eureka 并经由 Gateway 统一入口。

动手练习

在本地跑通 order-service,完成父 POM、多模块、Profile 与 Actuator 命令级验收。

操作步骤

  1. 确认 shopflow/pom.xml 含 spring-cloud.version 与 BOM import;在子模块手写 <version> 观察冲突后改回。
  2. 按「多模块拓扑」Mermaid,列出 order-service 允许依赖的 2 个模块,并说明为何不能依赖 inventory implementation。
  3. 配置 application-local.yml 端口,mvn spring-boot:run -Dspring-boot.run.profiles=local,curl -s localhost:8081/actuator/health 期望 UP。
  4. 在 common 添加 JSON Logback encoder,确认日志含 "service":"order-service"。

判断练习

  1. 端口写进 Java 静态字段且无 application-local.yml。两处应改回外部化的位置?违反哪条 Profile 约定?

    参考答案

    删除 Java 硬编码;在 application-local.yml 写 server.port,默认 application.yml 放共享项。违反「环境差异外部化、同一 artifact 多环境复用」。

  2. 子模块 pom 中 OpenFeign 写死 4.0.0,与 BOM 2025.0.1 并存。应删哪段?保留有何风险?

    参考答案

    删除子模块依赖上的 <version>4.0.0</version>,由 BOM 管理。保留可能导致与 Boot 3.5 矩阵不兼容、集成测试通过但生产 classpath 冲突。

Demo:ShopFlow 脚手架起步

目录:demos/practice-01-spring-cloud-bootstrap-lab/。验收:mvn install 成功 + health 为 UP + 改端口后仍可达。

延伸学习