發(fā)送 HTTP 請求(Java)
本文介紹 API 訂閱方應(yīng)用如何使用 Java 語言發(fā)送 HTTP 請求接入網(wǎng)關(guān)。
網(wǎng)關(guān)提供客戶端 Demo 代碼供用戶參考,下載 API 訂閱者 Demo 后,Demo 代碼位置為:src/test/java/com/alipay/gateway/web/test/usercase/mainchain/http/
前提條件
在進(jìn)行本地應(yīng)用開發(fā)前,您需要確保已經(jīng)完成以下操作:
已在 API 網(wǎng)關(guān)控制臺創(chuàng)建了一個應(yīng)用,參見 創(chuàng)建應(yīng)用。
已將該應(yīng)用的 APPID 提供給了 API 發(fā)布者,并獲得了授權(quán),參見 授權(quán) API。
已獲取了如下服務(wù)配置信息。具體獲取方法,參見 獲取服務(wù)端信息。
應(yīng)用的訪問密鑰(Access Key/Secret Key)
API 的域名地址(host)、請求路徑(path)、方法(method)、請求體(body)
操作步驟
API 網(wǎng)關(guān)提供了一個 Java SDK,即 gateway-sdk
。該 SDK 集成了加簽、加密、驗簽的邏輯,同時默認(rèn)支持序列化和反序列化。使用該 SDK 接入調(diào)用 HTTP 服務(wù)的操作步驟如下:
引入 SDK
您需要在本地工程 pom.xml
中添加如下 SDK。
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>gateway-sdk</artifactId>
<version>2.5.0</version>
</dependency>
創(chuàng)建 apiClient
使用獲取的 AK、SK、host 創(chuàng)建一個 APIClient,代碼示例如下:
如果 API 開啟了密鑰認(rèn)證,您還需要在工程中配置相應(yīng)的 Access Key 和 Secret Key,推薦使用啟動參數(shù)和環(huán)境變量的形式。
# 客戶端請求的ak、sk,就是應(yīng)用的密鑰信息
gateway.accessKey=<yourAccessKeyId>
gateway.secretKey=<yourAccessKeySecret>
apigateway.url=<yourGatewayURL>
apigateway.publicKey=<yourPublicKey>
@Value("${gateway.accessKey}")
private String accessKey;
@Value("${gateway.secretKey}")
private String secretKey;
@Value("${apigateway.url}")
private String gatewayurl;
@Value("${apigateway.publicKey}")
private final String publicKey;
@Before
public void initClient() {
// 初始化請求客戶端
ApiSecretKey apiSecretKey = new ApiSecretKey(gateway.accessKey, gateway.secretKey);
List<ApiSecretKey> secretKeys = new ArrayList<>();
//若無需加簽不需要添加secretKeys
secretKeys.add(apiSecretKey);
//無需加簽client
apiClientNoAuth = new DefaultApiClient(gatewayUrl);
//需要加簽client
apiClient = new DefaultApiClient(gatewayUrl, secretKeys);
//需要加密client,加密算法為RAS
//注意:需要加密的請求必須帶上secretKeys
encryptApiClient = new DefaultApiClient(gatewayUrl, secretKeys, EncryptEnum.RSA, publicKey);
//注意:以上的client根據(jù)所需場景創(chuàng)建一個即可
}
發(fā)起調(diào)用請求
apiClient 配置完成之后,即可對 API 發(fā)起調(diào)用。響應(yīng)會自動序列化到 response 對象里,直接使用即可,代碼示例如下:
@Test
public void testNoSignHttp() {
GwSdkApiRequest request = new GwSdkApiRequest();
request.setPath("simple/demo");//api路徑,前面不要帶上/,sdk會給path拼接/path的
request.setRequestType("POST");//請求方法 POST/GET/PUT/DELETE
//是否開啟加密,默認(rèn)為false
request.setNeedEncrypt(false);
// 是否對響應(yīng)進(jìn)行簽名校驗
request.setClientCheckSign(false);
//若網(wǎng)關(guān)沒有做泛域名代理或者dns解析需要傳請求頭 key : x-gateway-host ; value : api分組域名
request.getHeaderParams().put("x-gateway-host", CommonUtils.buildDomain(getGroupId()));
/*填寫入?yún)ⅲ且粋€object可以將實體類作為參數(shù)傳進(jìn)來,若想使用query方式傳參需要將參數(shù)拼接至gatewayUrl
注意:若api后端協(xié)議是SOFARPC/DUBBO入?yún)⒈仨毢秃蠖朔?wù)接口入?yún)⑼瓿梢恢保? 否則會出現(xiàn)序列化失敗或者找不到接口的情況,參數(shù)字段為空也需要傳{"key":null}
**/
request.setBody("{\"name\":\"tom\",\"age\":null}");
ApiResponse response = apiClient.execute(request);
System.out.println(JSON.toJSONString(response));
}
當(dāng)前網(wǎng)關(guān)需要通過域名輔助進(jìn)行 API 匹配,當(dāng)域名無法直接訪問時,可以通過 header 傳遞,具體方法請參加下文 通過 header 設(shè)置 host。
通過 header 設(shè)置 host
當(dāng)網(wǎng)關(guān)的域名無法直接訪問時,您可以發(fā)送請求到網(wǎng)關(guān),通過 header 設(shè)置 host 進(jìn)行訪問。
示例請求代碼如下:
在發(fā)送請求到網(wǎng)關(guān)時,您需要獲取 API 分組域名 和 API 網(wǎng)關(guān)公網(wǎng)域名 信息。
如果 API 開啟了密鑰認(rèn)證,您還需要在工程中配置相應(yīng)的 Access Key 和 Secret Key,推薦使用啟動參數(shù)和環(huán)境變量的形式。
# 客戶端請求的ak、sk,就是應(yīng)用的密鑰信息 gateway.accessKey=<yourAccessKeyId> gateway.secretKey=<yourAccessKeySecret> apigateway.url=<yourGatewayURL>
@Value("${gateway.accessKey}")
private String accessKey;
@Value("${gateway.secretKey}")
private String secretKey;
@Value("${apigateway.url}")
private String gatewayurl;
@Before
public void initClient() {
// 初始化請求客戶端
ApiSecretKey apiSecretKey = new ApiSecretKey(gateway.accessKey, gateway.secretKey);
List<ApiSecretKey> secretKeys = new ArrayList<>();
secretKeys.add(apiSecretKey);
apiClient = new DefaultApiClient(gatewayUrl, secretKeys);
}
@Test
public void testHost() {
ParamPostRequest request = new ParamPostRequest();
request.setPath("simple/demo");
// !??! 通過 header 設(shè)置分組 host ?。?!
request.getHeaderParams().put("x-gateway-host","5jzkcn0idt3w****.apigateway.inc.alipay.net");
// 是否對響應(yīng)進(jìn)行簽名校驗
request.setClientCheckSign(false);
ApiResponse response = apiClient.execute(request);
System.out.println(JSON.toJSONString(response));
}
注意事項
當(dāng) API 在測試環(huán)境完成測試后,通過導(dǎo)入導(dǎo)出功能把 API 信息遷移到生產(chǎn)環(huán)境,此時 API 對應(yīng)的分組域名會發(fā)生變換(分組名稱不變),所以最好通過在配置文件中配置域名的方式,將分組域名引入生產(chǎn)環(huán)境,方便客戶端區(qū)分生產(chǎn)環(huán)境和測試環(huán)境。
以下圖為例,在項目文件中,將以下代碼粘貼到對應(yīng)環(huán)境的 *.properties
文件中。
在application.properties中配置
subAppAccessKey=xxx
subAppSecretKey=xx
gatewayUrl=http://apigateway.alipay.com
#如果有多個分組可以配置多個key-value域名
apihost=aaaa.apigateway.inc.alipay.net
apihost1=xxx.apigateway.inc.alipay.net
apihost1=zzzz.apigateway.inc.alipay.net
@Value("${subAppAccessKey}")
private String subAppAccessKey ;
@Value("${subAppSecretKey}")
private String subAppSecretKey;
// !??!直接將請求發(fā)送給網(wǎng)關(guān),域名可以隨便定義
@Value("${gatewayUrl}")
private String gatewayUrl;
@Value("${apihost}")
private String apihost;
private ApiClient apiClient;
@Before
public void initClient() {
// 初始化請求客戶端
ApiSecretKey apiSecretKey = new ApiSecretKey(subAppAccessKey, subAppSecretKey);
List<ApiSecretKey> secretKeys = new ArrayList<>();
secretKeys.add(apiSecretKey);
apiClient = new DefaultApiClient(gatewayUrl, secretKeys);
}
@Test
public void testHost() {
ParamPostRequest request = new ParamPostRequest();
request.setPath("simple/demo");
// !??! 通過 header 設(shè)置分組 host !??!
request.getHeaderParams().put("x-gateway-host",apihost);
// 是否對響應(yīng)進(jìn)行簽名校驗
request.setClientCheckSign(false);
ApiResponse response = apiClient.execute(request);
System.out.println(JSON.toJSONString(response));
}