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

如何将外部API返回的JSON存入MultiKeyMap,消除Spring Boot项目硬编码实现动态逻辑

实现步骤

1. 引入所需依赖

首先在pom.xml中加入JSON解析和MultiKeyMap所需的依赖:

<!-- Jackson JSON解析 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>
<!-- Apache Commons Collections 包含MultiKeyMap -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

2. 定义航司配置实体类

创建和返回JSON字段对应的实体类,可搭配Lombok简化代码:

import lombok.Data;

@Data
public class AirlineConfig {
    private Integer id;
    private String airlineCode;
    private String supplierCode;
    private Integer portalConfigurationId;
    private Boolean enabled;
    private String microServiceName;
}

3. 解析API响应并存入MultiKeyMap

在原有调用配置接口的逻辑基础上,解析响应并存储到MultiKeyMap,这里使用supplierCode + microServiceName作为组合键,适配同一航司多个微服务的场景:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.collections4.map.MultiKeyMap;
import okhttp3.Response;
import java.util.List;

// 全局初始化ObjectMapper和OkHttpClient(建议注入Spring单例,不要重复创建)
ObjectMapper objectMapper = new ObjectMapper();
MultiKeyMap<String, AirlineConfig> airlineConfigMap = new MultiKeyMap<>();

// 原有配置接口调用逻辑,建议加try-with-resources自动释放响应
try (Response getActiveMicroservicesResponse = client.newCall(getActiveMicroservicesRequest).execute()) {
    if (getActiveMicroservicesResponse.isSuccessful() && getActiveMicroservicesResponse.body() != null) {
        String responseStr = getActiveMicroservicesResponse.body().string();
        JsonNode rootNode = objectMapper.readTree(responseStr);
        // 解析data数组为配置实体列表
        List<AirlineConfig> configList = objectMapper.convertValue(rootNode.get("data"), new TypeReference<List<AirlineConfig>>() {});
        // 存入MultiKeyMap,组合键为[供应商编码, 微服务名称]
        for (AirlineConfig config : configList) {
            airlineConfigMap.put(config.getSupplierCode(), config.getMicroServiceName(), config);
        }
    }
} catch (Exception e) {
    // 配置接口调用失败可降级使用本地默认配置,自行补充逻辑
    LOG.error("获取航司配置失败", e);
}

4. 遍历MultiKeyMap替换硬编码逻辑

将原有每个航司的重复硬编码逻辑替换为遍历逻辑,动态生成请求:

// 提前注入航司服务地址映射,配置在application.properties中,避免硬编码URL前缀
// 示例配置格式:airline.service-url.G8=http://xxx.xxx.xxx:8080
@Value("#{${airline.service-url}}")
private Map<String, String> serviceUrlMap;

// 遍历所有配置,只处理启用的搜索服务
int supplierCount = 0;
for (AirlineConfig config : airlineConfigMap.values()) {
    // 跳过未启用的航司 + 只处理搜索场景的微服务,可根据业务调整筛选条件
    if (!config.getEnabled() || !"search".equals(config.getMicroServiceName())) {
        continue;
    }
    String supplierCode = config.getSupplierCode();
    // 动态拼接请求地址
    String baseUrl = serviceUrlMap.get(supplierCode);
    String requestUrl = String.format("%s/%s/v1.0/search", baseUrl, supplierCode.toLowerCase());
    // 构造请求,复用原有body、公共请求头逻辑
    Request searchRequest = new Request.Builder().url(requestUrl).post(body)
            .addHeader("X-AFFILIATE-ID", request.getHeader("X-AFFILIATE-ID"))
            .addHeader("X-AFFILIATE-NAME", request.getHeader("X-AFFILIATE-NAME"))
            .addHeader("X-XL-CODE", request.getHeader("X-XL-CODE"))
            .addHeader("X-SEARCH-ID", uuId).build();
    Call call = client.newCall(searchRequest);
    // 异步回调逻辑,动态替换日志中的航司标识
    call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            MDC.setContextMap(mdcContext);
            LOG.debug("{} responded success, status Code: {}", supplierCode, response.code());
            response.close();
        }
        @Override
        public void onFailure(Call call, IOException e) {
            MDC.setContextMap(MDC.getCopyOfContextMap());
            LOG.error("Failure, Reason For {}: ", supplierCode, e);
        }
    });
    supplierCount++;
    LOG.info("Search initiated for {} , url: {}", supplierCode, requestUrl);
}

优化建议

  • 配置接口调用结果可加本地缓存,设置5-10分钟的过期时间,避免每次业务请求都重复拉取配置
  • OkHttpClient统一注册为Spring单例Bean,复用连接池提升性能
  • 可额外维护供应商编码和航司名称的映射字典,方便日志可读性

内容的提问来源于stack exchange,提问作者Nasheed Azhar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 16:45:03