泛化调用

更新时间:

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

特点

  1. 轻量级:仅需安装aliyun-java-sdk-core即可调用所有OpenAPI,无需依赖各产品的独立SDK。

  2. 快速迭代兼容性:当云产品尚未提供相应的SDK,或当新API发布但SDK未能及时更新时,可以使用泛化调用。这样,无需等待SDK的更新,即可及时调用最新发布的API接口。

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

使用说明

在使用泛化调用之前,必须手动获取并配置OpenAPI的版本号、请求路径、参数类型等元数据信息。可以通过查看OpenAPI元数据来获取有关OpenAPIAPI风格、请求参数、资源路径等相关信息。

安装核心SDK

pom.xml中添加以下依赖安装核心SDK。

<dependency>
     <groupId>com.aliyun</groupId>
     <artifactId>aliyun-java-sdk-core</artifactId>
     // 可选择版本
     <version>[(4.0.0,5.0.0)]</version>
</dependency>

调用OpenAPI

初始化请求客户端

通过在com.aliyuncs包中创建client对象以初始化请求客户端,并通过该Client发起OpenAPI调用。此处仅列举使用AccessKey(简称:AK)初始化客户端的方式,更多初始化方式请参见管理访问凭据

说明

为了避免凭据泄露,常见的方案是将其写入到环境变量中,具体操作请参见Linux、macOSWindows系统配置环境变量

 import com.aliyuncs.DefaultAcsClient;
 import com.aliyuncs.profile.DefaultProfile;
 
        // 1.创建DefaultAcsClient实例并初始化
        DefaultProfile profile = DefaultProfile.getProfile(
                // 您的地域ID
                "cn-hangzhou",
                // System.getenv表示从环境变量获取RAM账号的AccessKey ID
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
                // System.getenv表示从环境变量获取RAM账号的AccessKey SECRET
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        // Client HTTPS配置(可选)
        HttpClientConfig clientConfig = HttpClientConfig.getDefault();
//        // 设置不校验服务端证书
//        clientConfig.setIgnoreSSLCerts(true);
//        // 每个Host的最大连接数
//        clientConfig.setMaxRequestsPerHost(6);
//        // 连接超时时间
//        clientConfig.setConnectionTimeoutMillis(30000L);
//        // 读取超时时间
//        clientConfig.setReadTimeoutMillis(30000L);
//        // 写入超时时间
//        clientConfig.setWriteTimeoutMillis(60000L);
//        // 设置HTTP代理
//        clientConfig.setHttpProxy("http://127.0.0.1:9898");
//        // 设置HTTPS代理
//        clientConfig.setHttpsProxy("http://user:password@127.0.0.1:8989");
//        // 设置忽略代理地址列表
//        clientConfig.setNoProxy("127.0.0.1,localhost");

        profile.setHttpClientConfig(clientConfig);
        IAcsClient client = new DefaultAcsClient(profile);

配置OpenAPI基本信息及请求参数

通过CommonRequest来配置OpenAPI所需的公共请求参数及接口请求参数。关于更多公共请求参数的介绍及使用请参见进阶配置

说明

CommonRequest的核心作用在于通过标准化的请求配置流程,将原始API元数据(例如版本号、路径及参数类型)和请求参数转化为有效的HTTP请求,最终返回原始响应数据。参数传递方式的选择依据API风格和接口设计。

接口请求参数说明

请求参数应该如何传参需要查看接口对应的OpenAPI元数据,例如DescribeInstanceStatus的请求参数RegionId元数据中信息为{"name":"RegionId","in":"query",...}},其中"in":"query"表示RegionId通过putQueryParameter传递。

描述

传参方式

请求参数显示"in":"query"时。

putQueryParameter(String key,String value)

说明

如果请求参数的类型是集合,那么参数应该按照putQueryParameter("key.1","value1");

putQueryParameter("key.2","value2");...格式传参。

请求参数显示"in":"body""in": "formData"时。

putBodyParameter(String key,String value)

说明

如果请求参数的类型不是String类型,需要将参数值转为JSON字符串赋值给变量value。例如:request.putBodyParameter("key",new Gson().toJson(value));

上传文件时。

setHttpContent(byte[] content,String charset,FormatType formatType)

说明

其中参数formatType固定为FormatType.RAW。

        // 2.创建API请求并配置OpenAPI参数
        // 此示例以 RPC 风格 DescribeInstanceStatus(获取ECS实例状态信息)接口为例
        CommonRequest request = new CommonRequest();
        // 2.1 设置公共请求参数
        request.setSysMethod(com.aliyuncs.http.MethodType.POST);
        request.setSysDomain("ecs-cn-hangzhou.aliyuncs.com");// API的域名
        request.setSysVersion("2014-05-26");// API版本号
        request.setSysAction("DescribeInstanceStatus"); // API名称,当调用RPC风格API时,必须配置SysAction()指定接口名称
        request.setSysConnectTimeout(30000); // 超时时间
        request.setSysProtocol(com.aliyuncs.http.ProtocolType.HTTPS); //请求协议:HTTPS或HTTP,建议使用HTTPS。
//        request.setSysUriPattern("/"); // API资源路径,ROA接口必传。RPC接口禁止设置该参数。
        
        // 2.2 配置接口请求参数
        // 场景一:Query参数通过putQueryParameter(string key,string value)设置
        request.putQueryParameter("RegionId", "cn-hangzhou");
        List<String> instanceIds = List.of(
                "i-bp1axhql4dqXXXXXXXX",
                "i-bp124uve8zqXXXXXXXX"
        );
        for(int i = 0; i < instanceIds.size(); ++i) {
            request.putQueryParameter("InstanceId." + (i + 1), (String)instanceIds.get(i));
        }
        request.putQueryParameter("PageNumber", "1");
        request.putQueryParameter("PageSize", "30");

        // 场景二:body参数通过putBodyParameter(string key,string value)设置
        // request.putBodyParameter("key1", "value1");
        // request.putBodyParameter("key2", "value2");
        // request.putBodyParameter("key3", "value3");

        // 场景三:文件上传setHttpContent(byte[] content,String charset,FormatType formatType),其中formatType参数值固定为FormatType.RAW。
        // byte[] bodyImg = Files.readAllBytes(Paths.get("<FILE_PATH>")); // <FILE_PATH>需替换为实际文件路径
        // request.setHttpContent(bodyImg, "UTF-8", FormatType.RAW);
  

发起请求

通过client调用getCommonResponse发起请求。

// 发起请求
CommonResponse response = client.getCommonResponse(request);
// 返回值response.getData()是JSON类型数据,包含RequestId以及OpenAPI的返回参数
System.out.println(response.getData());

代码示例

示例:调用RPC风格的API

以调用ECSDescribeInstanceStatus接口为例,展示如何使用CommonRequest调用方式。

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.GsonBuilder;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class Sample {
    public static void main(String[] args) throws ClientException, UnsupportedEncodingException {
        // 创建DefaultAcsClient实例并初始化
        DefaultProfile profile = DefaultProfile.getProfile(
                // 您的地域ID
                "cn-hangzhou",
                // 从环境变量获取RAM账号的AccessKey ID
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
                // 从环境变量获取RAM账号的AccessKey SECRET
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        IAcsClient client = new DefaultAcsClient(profile);
        
        // 创建API请求并设置参数
        CommonRequest request = new CommonRequest();
        request.setSysMethod(com.aliyuncs.http.MethodType.POST); // 请求方式
        request.setSysDomain("ecs-cn-hangzhou.aliyuncs.com"); // API的域名
        request.setSysVersion("2014-05-26"); // API版本号
        request.setSysAction("DescribeInstanceStatus"); // API名称,当调用RPC风格API时,必须配置SysAction()指定接口名称
         request.setSysProtocol(com.aliyuncs.http.ProtocolType.HTTPS); //请求协议:HTTPS或HTTP,建议使用HTTPS。
        request.putQueryParameter("RegionId", "cn-hangzhou");
        List<String> instanceIds = List.of(
                "i-bp1axhql4dqXXXXXXXX",
                "i-bp124uve8zqXXXXXXXX"
        );
        for(int i = 0; i < instanceIds.size(); ++i) {
            request.putQueryParameter("InstanceId." + (i + 1), (String)instanceIds.get(i));
        }
        request.putQueryParameter("PageNumber", "1");
        request.putQueryParameter("PageSize", "30");
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
        } catch (ServerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClientException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

示例:调用RESTful(ROA)风格的API

以调用容器服务查询集群列表信息DescribeClustersV1接口为例,展示如何使用CommonRequest调用。

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
public class Sample {
    public static void main(String[] args) {
        // 创建DefaultAcsClient实例并初始化
        DefaultProfile profile = DefaultProfile.getProfile(
                // 您的地域ID
                "cn-hangzhou",
                // 从环境变量获取RAM账号的AccessKey ID
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
                // 从环境变量获取RAM账号的AccessKey SECRET
                System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        IAcsClient client = new DefaultAcsClient(profile);
        // 创建API请求并设置参数
        CommonRequest request = new CommonRequest();
        request.setSysDomain("cs.aliyuncs.com");// 域名
        request.setSysVersion("2015-12-15");// API版本
        request.setSysUriPattern("/clusters"); // API资源路径,当调用ROA风格API时,必须配置UriPattern()指定完整资源路径。从OpenAPI元数据中data.path获取资源路径。
        request.setSysMethod(MethodType.GET);// 请求方式
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
        } catch (ServerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClientException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

常见问题

  1. 报错提示“The input parameter "AccessKeyId" that is mandatory for processing this request is not supplied. ”。

    问题原因:AK未正确配置。

    解决方案:

    1. 执行以下命令,检查您的环境变量中是否配置有ALIBABA_CLOUD_ACCESS_KEY_IDALIBABA_CLOUD_ACCESS_KEY_SECRET:

      Linux/macOS

      echo $ALIBABA_CLOUD_ACCESS_KEY_ID
      echo $ALIBABA_CLOUD_ACCESS_KEY_SECRET

      Windows

      echo %ALIBABA_CLOUD_ACCESS_KEY_ID%
      echo %ALIBABA_CLOUD_ACCESS_KEY_SECRET%

      若返回正确的AccessKey,则说明配置成功。如果返回为空或错误,请尝试重新设置,具体操作请参见Linux、macOSWindows系统配置环境变量

    2. 检查代码中AK相关内容是否存在错误。

      常见错误示例:

      accessKeyId = System.getenv("yourAccessKeyID"),
      accessKeySecret = System.getenv("yourAccessKeySecret")
      说明

      此错误示例将System.getenv()的入参视为需要填入的AK,然而实际上该函数的功能是读取环境变量。当您在机器上设置环境变量名称为ALIBABA_CLOUD_ACCESS_KEY_IDALIBABA_CLOUD_ACCESS_KEY_SECRET时,System.getenv将能够获取其对应的值。

      正确示例

      System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")
      System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
  2. 报错提示“com.aliyuncs.exceptions.ClientException: MissingParameter : The input parameter "Timestamp" that is mandatory for processing this request is not supplied.”

    问题原因:RPC接口公共请求参数设置了SysUriPattern参数。

    解决方案:在公共请求参数中去掉SysUriPattern参数。