发送 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 服务的操作步骤如下:

  1. 引入 SDK

  2. 创建 apiClient

  3. 发起调用请求

引入 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 文件中。

1
在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));
    }