3. 开发环境与项目骨架搭建

FHIR 服务端不是普通的 CRUD 后端,它要处理资源版本、引用完整性、搜索参数、Bundle 事务、CapabilityStatement 等一整套规范约束。因此项目骨架必须在第一天就把“可运行、可观测、可配置、可调试”四件事固定下来,否则后续实现 Patient、Observation 等资源时会被环境问题反复打断。本节以 Java 生态为例,给出一个可直接落地的骨架方案;若团队使用 .NET 或 Node.js,结构思路一致,只是具体库名不同。

技术选型:先定运行时与框架边界

FHIR 服务端对 HTTP 语义、JSON/XML 序列化、并发与事务要求较高,推荐选型如下:运行时使用 JDK 17 或 21(LTS),构建工具用 Maven 3.9+;Web 框架选 Spring Boot 3.x,它自带内嵌 Tomcat、配置绑定和 Actuator,能直接满足健康检查需求。FHIR 模型层不建议手写 POJO,而是引入官方或社区维护的模型库,例如 ca.uhn.hapi.fhir:hapi-fhir-structures-r4,它提供 R4 全部资源的 Java 类型、解析器和校验器。持久层先用 H2 内存库跑通链路,再切换 PostgreSQL;搜索参数索引可借助 HAPI FHIR JPA 服务端模块,避免从零实现 _id、_lastUpdated、patient 等参数的解析与索引。

选型时要注意一个边界:FHIR 规范版本必须锁定。R4(4.0.1)与 R5 的资源字段差异明显,模型库、CapabilityStatement 和测试用例必须统一到同一版本,建议在 pom.xml 中用属性集中声明,例如 <fhir.version>4.0.1</fhir.version>,后续所有依赖引用该属性。

依赖管理:用 BOM 收敛版本

FHIR 相关依赖数量多、传递依赖深,最容易出现版本冲突。做法是引入 HAPI FHIR 的 BOM,把版本交给它统一管理,业务模块只声明 groupId 和 artifactId。示例片段如下:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>ca.uhn.hapi.fhir</groupId>
      <artifactId>hapi-fhir-bom</artifactId>
      <version>7.2.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>ca.uhn.hapi.fhir</groupId>
    <artifactId>hapi-fhir-structures-r4</artifactId>
  </dependency>
  <dependency>
    <groupId>ca.uhn.hapi.fhir</groupId>
    <artifactId>hapi-fhir-validation-resources-r4</artifactId>
  </dependency>
</dependencies>

依赖收敛后,用 mvn dependency:tree -Dincludes=ca.uhn.hapi.fhir 检查是否只剩一个版本号。若出现多个版本,优先通过 BOM 或 dependencyManagement 覆盖,而不是在业务模块里逐个 exclusion。

配置管理:环境隔离与敏感信息外置

骨架阶段就要建立 application.yml 加 profile 的结构:application.yml 放通用项,application-local.yml 放本地 H2 与调试开关,application-prod.yml 放 PostgreSQL 与连接池。FHIR 服务端的关键配置包括:服务基础路径(如 /fhir)、默认 FHIR 版本、是否开启校验、分页默认条数。示例:

fhir:
  server:
    path: /fhir
    version: R4
    validation-enabled: true
    default-page-size: 20
spring:
  datasource:
    url: jdbc:h2:mem:fhir;DB_CLOSE_DELAY=-1
    username: sa
    password: ""

数据库口令、密钥等敏感项不要写进仓库,用环境变量覆盖,例如 SPRING_DATASOURCE_PASSWORD。Spring Boot 的松散绑定会自动把下划线环境变量映射到配置项,无需额外代码。

日志与健康检查:让问题可见

日志建议用 Logback,输出格式包含时间、级别、线程、logger 和 traceId。FHIR 请求量大,必须能按请求追踪,可在过滤器中为每个请求生成 traceId 并放入 MDC。健康检查直接启用 Actuator,暴露 /actuator/health,并自定义一个 FhirCapabilityHealthIndicator,检查模型库能否正常构建 CapabilityStatement、数据库连接是否可用。返回 {"status":"UP","components":{"fhir":{"status":"UP","fhirVersion":"4.0.1"}}} 即表示骨架健康。

FHIR 服务端项目骨架:分层与关键组件 FHIR 客户端 REST / Bundle 接入层 /fhir 路由 · traceId 过滤器 内容协商 JSON/XML FHIR 服务层 资源解析 · 校验 · 搜索参数 CapabilityStatement 持久层 H2 / PostgreSQL 搜索索引表 配置管理 application.yml + profile 环境变量覆盖敏感项 日志 Logback · MDC traceId 请求级追踪 健康检查 Actuator /health FHIR 能力自检 本地运行与调试 mvn spring-boot:run -Dspring-boot.run.profiles=local 断点调试 · H2 控制台 · curl 验证 /fhir/metadata

本地运行与调试环境

骨架完成后,用 mvn spring-boot:run -Dspring-boot.run.profiles=local 启动。启动日志中应能看到 Tomcat 监听端口、H2 初始化完成、Actuator 端点注册三类信息。随后用 curl 验证:

curl -s http://localhost:8080/fhir/metadata | head -c 300
curl -s http://localhost:8080/actuator/health

第一条应返回 CapabilityStatement 的 JSON 片段,包含 "resourceType":"CapabilityStatement" 和 "fhirVersion":"4.0.1";第二条应返回 {"status":"UP"}。若 metadata 返回 404,检查 fhir.server.path 是否与请求路径一致;若 health 为 DOWN,查看 components 中哪个指标失败。调试时可在资源解析入口打断点,观察传入的 IBaseResource 类型与校验结果,这比反复打印日志更高效。

建议把上述两条 curl 命令写进 scripts/smoke.sh,每次改完配置先跑一遍,作为骨架是否仍然健康的快速回归。

至此,项目骨架具备了明确的技术边界、收敛的依赖、可切换的配置、可追踪的日志和可验证的健康状态。后续实现具体资源交互时,只需在服务层和持久层内扩展,不必再回头调整环境结构。