You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HAPI FHIR Client获取Patient后Spring MVC返回404及JSON转换问题

问题分析与解决方案

核心问题定位

你能通过HAPI的JSON解析器正确序列化Patient对象并打印,但控制器返回时出现404(entity-not-found),本质不是资源不存在,而是Spring MVC在序列化FHIR资源时配置错误,导致响应处理异常,被框架误映射为404错误。

关键错误修正

1. 修复HapiHttpMessageConverter的核心配置

你的代码中创建HapiHttpMessageConverter时未传入FhirContext,这会导致转换器无法识别FHIR资源结构,无法完成序列化。必须关联对应的FHIR上下文(R4版本)。

2. 移除冲突的Jackson转换器

Jackson默认无法正确处理FHIR资源的特殊结构(如多态、扩展字段等),保留自定义的MappingJackson2HttpMessageConverter会让Spring优先尝试用Jackson序列化,导致失败。

3. 明确控制器的响应MediaType

在控制器方法上指定produces = "application/fhir+json",确保Spring调用正确的消息转换器处理响应。

4. 移除多余的类型注册

Patient是HAPI内置的FHIR R4资源类型,无需手动调用registerCustomType。

修正后的完整代码

配置类(FHIR与WebMvc)

@Configuration
public class FhirConfig implements WebMvcConfigurer {

    private final String fhirServerBase = "https://api.logicahealth.org/DVJan21CnthnPDex/open";

    @Bean
    public FhirContext fhirContext() {
        return FhirContext.forR4();
    }

    @Bean
    public IGenericClient fhirClient(FhirContext fhirContext) {
        return fhirContext.newRestfulGenericClient(fhirServerBase);
    }

    @Bean
    public HapiHttpMessageConverter hapiHttpMessageConverter(FhirContext fhirContext) {
        // 必须传入FhirContext,让转换器知道使用R4版本的解析规则
        return new HapiHttpMessageConverter(fhirContext);
    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
        // 将HAPI转换器放在最前面,确保优先被Spring选中
        messageConverters.add(0, hapiHttpMessageConverter(fhirContext()));
    }
}

控制器代码

@RestController
@RequestMapping("/patients")
public class PatientController {

    private final IGenericClient fhirClient;

    // 构造注入FHIR客户端
    public PatientController(IGenericClient fhirClient) {
        this.fhirClient = fhirClient;
    }

    @GetMapping(value = "/{identifier}", produces = "application/fhir+json")
    public Patient getPatient(@PathVariable String identifier) {
        Bundle bundle = fhirClient.search()
                .forResource(Patient.class)
                .where(Patient.IDENTIFIER.exactly().identifier(identifier))
                .returnBundle(Bundle.class)
                .execute();

        // 真实的资源不存在场景,主动抛出404
        if (bundle.getEntry() == null || bundle.getEntry().isEmpty()) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Patient not found");
        }

        return (Patient) bundle.getEntry().get(0).getResource();
    }
}

额外注意事项

  • 确保依赖正确:如果使用Maven,需引入hapi-fhir-spring-boot-starter或hapi-fhir-structures-r4、hapi-fhir-client等核心依赖
  • 请求时需确保客户端Accept头包含application/fhir+json(浏览器测试可通过Postman等工具指定)
  • 若仍有问题,开启Spring DEBUG日志,查看org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor相关日志,确认消息转换器的选择是否正确

内容的提问来源于stack exchange,提问作者Yaroslav Lukianenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:37:03