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"}}} 即表示骨架健康。
本地运行与调试环境
骨架完成后,用 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 类型与校验结果,这比反复打印日志更高效。
scripts/smoke.sh,每次改完配置先跑一遍,作为骨架是否仍然健康的快速回归。至此,项目骨架具备了明确的技术边界、收敛的依赖、可切换的配置、可追踪的日志和可验证的健康状态。后续实现具体资源交互时,只需在服务层和持久层内扩展,不必再回头调整环境结构。