发送 HTTP 请求(Java)
本文介绍 API 订阅方应用如何使用 Java 语言发送 HTTP 请求接入网关。
网关提供客户端 Demo 代码供用户参考,下载 API 订阅者 Demo 后,Demo 代码位置为:src/test/java/com/alipay/gateway/web/test/usercase/mainchain/http/
前提条件
在进行本地应用开发前,您需要确保已经完成以下操作:
已在 API 网关控制台创建了一个应用,参见 创建应用。
已将该应用的 APPID 提供给了 API 发布者,并获得了授权,参见 授权 API。
已获取了如下服务配置信息。具体获取方法,参见 获取服务端信息。
应用的访问密钥(Access Key/Secret Key)
API 的域名地址(host)、请求路径(path)、方法(method)、请求体(body)
操作步骤
API 网关提供了一个 Java SDK,即 gateway-sdk
。该 SDK 集成了加签、加密、验签的逻辑,同时默认支持序列化和反序列化。使用该 SDK 接入调用 HTTP 服务的操作步骤如下:
引入 SDK
您需要在本地工程 pom.xml
中添加如下 SDK。
<dependency>
<groupId>com.alipay.sofa</groupId>
<artifactId>gateway-sdk</artifactId>
<version>2.5.0</version>
</dependency>
创建 apiClient
使用获取的 AK、SK、host 创建一个 APIClient,代码示例如下:
如果 API 开启了密钥认证,您还需要在工程中配置相应的 Access Key 和 Secret Key,推荐使用启动参数和环境变量的形式。
# 客户端请求的ak、sk,就是应用的密钥信息
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根据所需场景创建一个即可
}
发起调用请求
apiClient 配置完成之后,即可对 API 发起调用。响应会自动序列化到 response 对象里,直接使用即可,代码示例如下:
@Test
public void testNoSignHttp() {
GwSdkApiRequest request = new GwSdkApiRequest();
request.setPath("simple/demo");//api路径,前面不要带上/,sdk会给path拼接/path的
request.setRequestType("POST");//请求方法 POST/GET/PUT/DELETE
//是否开启加密,默认为false
request.setNeedEncrypt(false);
// 是否对响应进行签名校验
request.setClientCheckSign(false);
//若网关没有做泛域名代理或者dns解析需要传请求头 key : x-gateway-host ; value : api分组域名
request.getHeaderParams().put("x-gateway-host", CommonUtils.buildDomain(getGroupId()));
/*填写入参,他是一个object可以将实体类作为参数传进来,若想使用query方式传参需要将参数拼接至gatewayUrl
注意:若api后端协议是SOFARPC/DUBBO入参必须和后端服务接口入参完成一直,
否则会出现序列化失败或者找不到接口的情况,参数字段为空也需要传{"key":null}
**/
request.setBody("{\"name\":\"tom\",\"age\":null}");
ApiResponse response = apiClient.execute(request);
System.out.println(JSON.toJSONString(response));
}
当前网关需要通过域名辅助进行 API 匹配,当域名无法直接访问时,可以通过 header 传递,具体方法请参加下文 通过 header 设置 host。
通过 header 设置 host
当网关的域名无法直接访问时,您可以发送请求到网关,通过 header 设置 host 进行访问。
示例请求代码如下:
在发送请求到网关时,您需要获取 API 分组域名 和 API 网关公网域名 信息。
如果 API 开启了密钥认证,您还需要在工程中配置相应的 Access Key 和 Secret Key,推荐使用启动参数和环境变量的形式。
# 客户端请求的ak、sk,就是应用的密钥信息 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 设置分组 host !!!
request.getHeaderParams().put("x-gateway-host","5jzkcn0idt3w****.apigateway.inc.alipay.net");
// 是否对响应进行签名校验
request.setClientCheckSign(false);
ApiResponse response = apiClient.execute(request);
System.out.println(JSON.toJSONString(response));
}
注意事项
当 API 在测试环境完成测试后,通过导入导出功能把 API 信息迁移到生产环境,此时 API 对应的分组域名会发生变换(分组名称不变),所以最好通过在配置文件中配置域名的方式,将分组域名引入生产环境,方便客户端区分生产环境和测试环境。
以下图为例,在项目文件中,将以下代码粘贴到对应环境的 *.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;
// !!!直接将请求发送给网关,域名可以随便定义
@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 设置分组 host !!!
request.getHeaderParams().put("x-gateway-host",apihost);
// 是否对响应进行签名校验
request.setClientCheckSign(false);
ApiResponse response = apiClient.execute(request);
System.out.println(JSON.toJSONString(response));
}