泛化调用

更新时间:

阿里云SDK支持一种通用的方式调用OpenAPI,此方式被称为泛化调用。本文将为您详细介绍如何使用泛化调用访问OpenAPI。

特点

轻量级:仅需安装阿里云核心SDK,无需额外安装云产品SDK。

易用性:通过构建统一参数对象,使用通用客户端调用通用接口即可完成API调用,响应结果均采用统一标准格式返回。

更多介绍,请参见泛化调用与特化调用

使用说明

使用泛化调用时,建议先查看OpenAPI元数据或者帮助中心各个云产品的开发参考文档,获取API风格、API版本、API请求参数等信息。

安装核心SDK

pom.xml中添加以下依赖安装核心SDK,最新版本请参见Maven Central

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>aliyun-gateway-pop</artifactId>
    <version>last-version</version>
</dependency>

调用OpenAPI

1. 初始化异步客户端

所有OpenAPI均通过com.aliyun.sdk.gateway.pop.clients.CommonAsyncClient实例提供的方法发起调用,因此在调用OpenAPI之前需要完成异步客户端的初始化。初始化过程中需要配置访问凭据提供者,本文以采用静态凭据提供者为例,如需了解其他类型的访问凭据获取方案,请参见管理访问凭据

说明
  • 该方式创建的异步客户端实例是线程安全的,能够在多线程环境中安全使用。实际开发过程中建议采用单例模式封装异步客户端,确保在整个应用程序生命周期中针对相同的访问凭据和Endpoint仅初始化一个异步客户端实例。

  • SDK中默认使用连接池管理异步HTTP请求,当默认配置不符合您的业务需求时,您可以通过重新配置连接池参数进行调整。具体操作请参见HTTP连接池配置

  • 异步客户端的更多配置,请参见进阶配置

示例代码如下:

// 以StaticCredentialProvider为例
com.aliyun.auth.credentials.provider.StaticCredentialProvider provider = com.aliyun.auth.credentials.provider.StaticCredentialProvider.create(
        com.aliyun.auth.credentials.Credential.builder()
                // 必填,从环境变量中获取RAM用户的AccessKey ID
                .accessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
                // 必填,从环境变量中获取RAM用户的AccessKey Secret
                .accessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
                .build()
);
// 创建CommonAsyncClient实例
com.aliyun.sdk.gateway.pop.clients.CommonAsyncClient client = com.aliyun.sdk.gateway.pop.clients.CommonAsyncClient.builder()
        .credentialsProvider(provider)
        .overrideConfiguration(
                darabonba.core.client.ClientOverrideConfiguration.create()
                        // 设置请求协议,非必填,默认HTTPS
                        .setProtocol("HTTPS")
                        // 设置云产品的Endpoint,必填,更多Endpoint设置方式请查阅Endpoint配置
                        .setEndpointOverride("<ENDPOINT>")
        )
        .build();

2. 配置调用参数

通过com.aliyun.sdk.gateway.pop.models.CommonRequest配置调用参数,调用参数包含OpenAPI基本信息参数和接口请求参数。

OpenAPI基本信息参数:

参数名称

参数说明

product

产品CODE,可从元数据中获取。例如ECS、RAM。

version

API版本,可从元数据中获取。例如ECSAPI版本为2014-05-26。

action

OpenAPI名称,例如查询ECS实例列表对应的OpenAPI名称为DescribeInstances

path

资源路径,可从元数据中获取。RPC接口该参数值为/;ROA接口该参数值为具体的资源路径,例如百炼创建索引接口的资源路径为/{WorkspaceId}/index/create,其中{WorkspaceId}需要改成具体业务的值。

httpMethod

请求方法,默认值为GET

requestBodyType

请求body的类型,支持jsonform,默认值为json,如何选择与接口请求参数有关。

接口请求参数:

请求参数支持通过putQueryParametersputBodyParametersputBodyStream传参,如何选择传参方式可根据元数据中的介绍选择。例如在DescribeInstances元数据{"name":"RegionId","in":"query",...}},其中"in":"query"表示RegionId通过putQueryParameters传递。

参数名称

参数说明

putQueryParameters

请求参数显示"in":"query"时,通过putQueryParameters传递参数,requestBodyType使用默认值即可。

putBodyParameters

请求参数显示"in":"body""in": "formData"时,通过putBodyParameters传递参数,同时需要根据请求体的类型设置requestBodyType的值。

putBodyStream

在需要上传文件的场景,可通过putBodyStream传递文件流,requestBodyType使用默认值即可。

示例代码如下:

// 示例一:设置查询参数("query")
com.aliyun.sdk.gateway.pop.models.CommonRequest commonRequest = com.aliyun.sdk.gateway.pop.models.CommonRequest.builder()
        .product("ECS")
        .version("2014-05-26")
        .action("DescribeInstances")
        .path("/")
        .httpMethod(com.aliyun.core.http.HttpMethod.POST) // 请求方法,非必填。默认为HttpMethod.GET
        .putQueryParameters("RegionId", "cn-chengdu")
        .putQueryParameters("InstanceIds", new com.google.gson.Gson().toJson(java.util.Collections.singletonList("i-2vc6*************")))
        .build();

//        // 示例二:设置body参数("formData"),requestBodyType的值为form
//        com.aliyun.sdk.gateway.pop.models.CommonRequest commonRequest = com.aliyun.sdk.gateway.pop.models.CommonRequest.builder()
//                .product("alimt")
//                .version("2018-10-12")
//                .action("TranslateGeneral")
//                .path("/")
//                .httpMethod(com.aliyun.core.http.HttpMethod.POST)
//                .requestBodyType("form") // 请求体类型为form
//                .putBodyParameters("FormatType", "text")
//                .putBodyParameters("SourceLanguage", "en")
//                .putBodyParameters("TargetLanguage", "zh")
//                .putBodyParameters("SourceText", "hello")
//                .putBodyParameters("Scene", "general")
//                .build();

//        // 示例三:设置body参数("body"),requestBodyType的值为json
//        com.aliyun.sdk.gateway.pop.models.CommonRequest commonRequest = com.aliyun.sdk.gateway.pop.models.CommonRequest.builder()
//                .product("bailian")
//                .version("2023-12-29")
//                .action("AddCategory")
//                .path("/llm-p2e4************/datacenter/category")
//                .httpMethod(com.aliyun.core.http.HttpMethod.POST)
//                .requestBodyType("json")
//                .putBodyParameters("CategoryName", "test_category")
//                .putBodyParameters("CategoryType", "UNSTRUCTURED")
//                .build();

//        // 示例四:使用Stream流参数传递文件流
//        java.io.InputStream io = new java.io.ByteArrayInputStream(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get("D:\\test.jpeg")));
//        com.aliyun.sdk.gateway.pop.models.CommonRequest commonRequest = com.aliyun.sdk.gateway.pop.models.CommonRequest.builder()
//                .product("ocr")
//                .version("2021-07-07")
//                .action("RecognizeGeneral")
//                .path("/")
//                .httpMethod(com.aliyun.core.http.HttpMethod.POST)
//                .putBodyStream(io)
//                .build();

3. 发起请求

通过步骤1创建的异步客户端实例调用callApi发起请求,参数为步骤2构造的CommonRequest实例。

java.util.concurrent.CompletableFuture<com.aliyun.sdk.gateway.pop.models.CommonResponse> responseCompletableFuture = client.callApi(commonRequest);
com.aliyun.sdk.gateway.pop.models.CommonResponse response = responseCompletableFuture.join();

完整代码示例

import com.aliyun.httpcomponent.httpclient.ApacheAsyncHttpClientBuilder;
import com.aliyun.sdk.gateway.pop.models.CommonRequest;
import com.aliyun.sdk.gateway.pop.models.CommonResponse;
import com.google.gson.Gson;
import darabonba.core.RequestConfiguration;
import com.aliyun.core.http.HttpClient;

import java.io.IOException;
import java.time.Duration;
import java.util.Collections;
import java.util.concurrent.CompletableFuture;

public class Demo {
    public static void main(String[] args) throws IOException {
        com.aliyun.auth.credentials.provider.StaticCredentialProvider provider = com.aliyun.auth.credentials.provider.StaticCredentialProvider.create(
                com.aliyun.auth.credentials.Credential.builder()
                        // 必填,从环境变量中获取RAM用户的AccessKey ID
                        .accessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
                        // 必填,从环境变量中获取RAM用户的AccessKey Secret
                        .accessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
                        .build()
        );
        HttpClient httpClient = new ApacheAsyncHttpClientBuilder()
                // 连接池相关参数
                .maxConnections(128) // 设置连接池大小,默认值128。
                .maxConnectionsPerRoute(128) // 设置每路由最大连接数,默认值128。
                .maxIdleTimeOut(Duration.ofMillis(20000)) // 设置连接在连接池中的最大空闲时间,默认30000毫秒。
                .keepAlive(Duration.ofMillis(20000)) // 连接的空闲存活时间,默认值20000毫秒。
                .connectRequestTimeout(Duration.ofMillis(30000)) // 获取连接的超时时间,默认值30000毫秒。
                // 使用HTTPS协议时,可配置SSL/TLS相关参数
                // .x509TrustManagers(null) // 配置自定义的CA证书信任管理器,非必传。
                // .keyManagers(null) // 配置客户端密钥管理器,非必传。
                // .ignoreSSL(false) // 是否跳过证书检查,默认false,非必传。
                // .hostnameVerifier(null) // 自定义HTTPS主机名验证规则,需自主实现javax.net.ssl.HostnameVerifier,非必传。
                // 代理配置参数
                .proxy(new com.aliyun.core.http.ProxyOptions(
                        com.aliyun.core.http.ProxyOptions.Type.HTTP,
                        new java.net.InetSocketAddress("<YOUR-PROXY-HOSTNAME>", 9001) // 代理地址及端口号
                ).setCredentials("<YOUR-PROXY-USERNAME>", "<YOUR-PROXY-PASSWORD>"))
                // 超时时间
                .connectionTimeout(Duration.ofMillis(10000)) // 默认连接超时时间为10000毫秒
                .responseTimeout(Duration.ofMillis(20000)) // 默认响应超时为20000毫秒
                .build();

        com.aliyun.sdk.gateway.pop.clients.CommonAsyncClient client = com.aliyun.sdk.gateway.pop.clients.CommonAsyncClient.builder()
                .credentialsProvider(provider)
                .httpClient(httpClient)
                .build();

        // 示例一:设置查询参数("query")
        CommonRequest commonRequest = CommonRequest.builder()
                .product("ECS")
                .version("2014-05-26")
                .action("DescribeInstances")
                .path("/")
                .httpMethod(com.aliyun.core.http.HttpMethod.POST) // 请求方法,非必填。默认为HttpMethod.GET
                .putQueryParameters("RegionId", "cn-chengdu")
                .putQueryParameters("InstanceIds", new Gson().toJson(Collections.singletonList("i-2vc6*************")))
                .requestConfiguration(RequestConfiguration.create()
                        .setEndpointOverride("ecs.cn-chengdu.aliyuncs.com")) // ecs endpoint
                .build();

        // 示例二:设置body参数("formData"),reqBodyType的值为form
//        com.aliyun.sdk.gateway.pop.models.CommonRequest commonRequest = com.aliyun.sdk.gateway.pop.models.CommonRequest.builder()
//                .product("alimt")
//                .version("2018-10-12")
//                .action("TranslateGeneral")
//                .path("/")
//                .httpMethod(com.aliyun.core.http.HttpMethod.POST)
//                .requestBodyType("form") // 请求体类型为form
//                .putBodyParameters("FormatType", "text")
//                .putBodyParameters("SourceLanguage", "en")
//                .putBodyParameters("TargetLanguage", "zh")
//                .putBodyParameters("SourceText", "hello")
//                .putBodyParameters("Scene", "general")
//                .requestConfiguration(RequestConfiguration.create()
//                        .setEndpointOverride("mt.aliyuncs.com")) // alimt endpoint
//                .build();

        // 示例三:设置body参数("body"),reqBodyType的值为json
//        com.aliyun.sdk.gateway.pop.models.CommonRequest commonRequest = com.aliyun.sdk.gateway.pop.models.CommonRequest.builder()
//                .product("bailian")
//                .version("2023-12-29")
//                .action("AddCategory")
//                .path("/llm-p2e4************/datacenter/category")
//                .httpMethod(com.aliyun.core.http.HttpMethod.POST)
//                .requestBodyType("json")
//                .putBodyParameters("CategoryName", "test_category")
//                .putBodyParameters("CategoryType", "UNSTRUCTURED")
//                .requestConfiguration(RequestConfiguration.create()
//                        .setEndpointOverride("bailian.cn-beijing.aliyuncs.com")) // bailian endpoint
//                .build();

        // 示例四:使用Stream流参数传递文件流
//        java.io.InputStream io = new java.io.ByteArrayInputStream(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get("D:\\test.jpeg")));
//        com.aliyun.sdk.gateway.pop.models.CommonRequest commonRequest = com.aliyun.sdk.gateway.pop.models.CommonRequest.builder()
//                .product("ocr")
//                .version("2021-07-07")
//                .action("RecognizeGeneral")
//                .path("/")
//                .httpMethod(com.aliyun.core.http.HttpMethod.POST)
//                .putBodyStream(io)
//                .requestConfiguration(RequestConfiguration.create()
//                        .setEndpointOverride("ocr-api.cn-hangzhou.aliyuncs.com")) // ocr endpoint
//                .build();

        CompletableFuture<CommonResponse> responseCompletableFuture = client.callApi(commonRequest);
        CommonResponse response = responseCompletableFuture.join();
        System.out.println(response.getHeaders());
        System.out.println(new Gson().toJson(response.getBody()));
    }
}