主题
ApiOne Spring Boot 集成指南
重要:根据项目分层规范,ApiOne 调用逻辑必须位于 Manager 层,而非 Service 层。
1. application.yml 配置
yaml
apione:
# 每个 apiName 独立配置 ak/sk/url/region
apis:
user-info-query:
request-url: https://api-one-dev.digitalhainan.com.cn/apione
ak: ${APIONE_USER_INFO_AK}
sk: ${APIONE_USER_INFO_SK}
region: INTRA
api-name: user.info.query
user-list-query:
request-url: https://api-one-dev.digitalhainan.com.cn/apione
ak: ${APIONE_USER_LIST_AK}
sk: ${APIONE_USER_LIST_SK}
region: INTRA
api-name: user.list.query
order-info-query:
request-url: https://api-one-prod.digitalhainan.com.cn/apione
ak: ${APIONE_ORDER_AK}
sk: ${APIONE_ORDER_SK}
region: PUBLIC
api-name: order.info.query2. 配置属性类
java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
@ConfigurationProperties(prefix = "apione")
public class ApioneProperties {
// key=业务标识, value=接口配置(含独立 ak/sk/url/region/apiName)
private Map<String, ApiConfig> apis = new HashMap<>();
public Map<String, ApiConfig> getApis() {
return apis;
}
public void setApis(Map<String, ApiConfig> apis) {
this.apis = apis;
}
public static class ApiConfig {
private String requestUrl;
private String ak;
private String sk;
private String region = "INTRA";
private String apiName; // 实际接口名称
// Getters and Setters
public String getRequestUrl() { return requestUrl; }
public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; }
public String getAk() { return ak; }
public void setAk(String ak) { this.ak = ak; }
public String getSk() { return sk; }
public void setSk(String sk) { this.sk = sk; }
public String getRegion() { return region; }
public void setRegion(String region) { this.region = region; }
public String getApiName() { return apiName; }
public void setApiName(String apiName) { this.apiName = apiName; }
}
}3. 客户端封装类
java
import cn.com.digitalhainan.apione.sdk.ContentBody;
import cn.com.digitalhainan.apione.sdk.HttpCaller;
import cn.com.digitalhainan.apione.sdk.HttpParameters;
import cn.com.digitalhainan.apione.sdk.HttpReturn;
import okhttp3.MediaType;
import java.util.Map;
/**
* ApiOne 客户端封装类(每个接口独立配置)
*/
public class ApioneClient {
private final String requestUrl;
private final String ak;
private final String sk;
private final String region;
private final String apiName;
public ApioneClient(String requestUrl, String ak, String sk, String region, String apiName) {
this.requestUrl = requestUrl;
this.ak = ak;
this.sk = sk;
this.region = region;
this.apiName = apiName;
}
/**
* 调用 ApiOne 接口
*/
public String call(String jsonBody) {
return doCall(jsonBody, null, null, null, "application/json");
}
/**
* 调用 ApiOne 接口(含 Query 参数)
*/
public String callWithQuery(String jsonBody, Map<String, String> queryParams) {
return doCall(jsonBody, null, queryParams, null, "application/json");
}
/**
* 调用 ApiOne 接口(含 Path 参数)
*/
public String callWithPath(String jsonBody, String path) {
return doCall(jsonBody, path, null, null, "application/json");
}
private String doCall(String jsonBody, String path,
Map<String, String> queryParams, Map<String, String> headerParams,
String mediaType) {
ContentBody contentBody = new ContentBody(jsonBody != null ? jsonBody : "{}");
HttpParameters parameters = HttpParameters.builder()
.api(apiName)
.region(region)
.mediaType(MediaType.parse(mediaType))
.accessKey(ak)
.secretKey(sk)
.contentBody(contentBody)
.requestUrl(requestUrl)
.build();
if (path != null && !path.isEmpty()) {
parameters.setPath(path);
}
if (queryParams != null && !queryParams.isEmpty()) {
parameters.setQueryParamsMap(queryParams);
}
if (headerParams != null && !headerParams.isEmpty()) {
parameters.setHeaderParamsMap(headerParams);
}
HttpReturn httpReturn = HttpCaller.getInstance().call(parameters);
return httpReturn.getResponse();
}
}4. 配置类
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ApioneConfig {
@Autowired
private ApioneProperties apioneProperties;
// key=业务标识, value=客户端实例
private final Map<String, ApioneClient> clientMap = new HashMap<>();
@PostConstruct
public void init() {
Map<String, ApioneProperties.ApiConfig> apis = apioneProperties.getApis();
if (apis != null) {
apis.forEach((key, config) -> {
ApioneClient client = new ApioneClient(
config.getRequestUrl(),
config.getAk(),
config.getSk(),
config.getRegion(),
config.getApiName()
);
clientMap.put(key, client);
});
}
}
public ApioneClient getClient(String apiKey) {
ApioneClient client = clientMap.get(apiKey);
if (client == null) {
throw new IllegalArgumentException("未找到 apiKey '" + apiKey + "' 的 ApiOne 配置");
}
return client;
}
// 预定义客户端 Bean
@Bean(name = "userInfoQueryClient")
public ApioneClient userInfoQueryClient() {
return getClient("user-info-query");
}
@Bean(name = "userListQueryClient")
public ApioneClient userListQueryClient() {
return getClient("user-list-query");
}
@Bean(name = "orderInfoQueryClient")
public ApioneClient orderInfoQueryClient() {
return getClient("order-info-query");
}
}5. Manager 层调用示例
分层规范:ApiOne 调用必须位于 Manager 层,Controller -> Manager -> ApiOne。
java
package cn.szhn.demo.business.user.manager.impl;
import cn.szhn.demo.api.user.vo.UserVO;
import cn.szhn.demo.business.user.manager.UserManager;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
public class UserManagerImpl implements UserManager {
// 每个 apiName 对应独立的客户端(独立 ak/sk/url/region)
@Autowired
@Qualifier("userInfoQueryClient")
private ApioneClient userInfoQueryClient;
@Autowired
@Qualifier("userListQueryClient")
private ApioneClient userListQueryClient;
@Autowired
@Qualifier("orderInfoQueryClient")
private ApioneClient orderInfoQueryClient;
@Override
public UserDTO getUserInfo(String userId) {
String jsonBody = "{\"userId\":\"" + userId + "\"}";
String response = userInfoQueryClient.call(jsonBody);
return JacksonMapper.alwaysMapper.fromJson(response, UserDTO.class);
}
@Override
public List<UserDTO> listUsers(int pageNum, int pageSize) {
String jsonBody = "{}";
Map<String, String> queryParams = Map.of(
"pageNum", String.valueOf(pageNum),
"pageSize", String.valueOf(pageSize)
);
String response = userListQueryClient.callWithQuery(jsonBody, queryParams);
JavaType listType = JacksonMapper.alwaysMapper.createCollectionType(
List.class, UserDTO.class);
List<User> userList2 = JacksonMapper.alwaysMapper.fromJson(response, listType);
return userList2;
}
@Override
public String getOrderInfo(String orderId) {
String jsonBody = "{\"orderId\":\"" + orderId + "\"}";
// 调用订单服务(独立的 ak/sk/url/region)
return orderInfoQueryClient.call(jsonBody);
}
}调用链路
Controller -> Manager (UserManagerImpl) -> ApioneClient -> ApiOne API每个 apiName 都有独立的配置(ak、sk、url、region),通过 Spring Bean 注入到 Manager 层使用。
