附录:API调用示例

API可使用SDK调用方式及白名单免密调用方式。其中仅使用私有网关的时候支持白名单方式。本篇API调用示例为调用模板,您可根据模板配置API的调用示例。

SDK调用

Java SDK简介

Dataphin数据服务Java SDK为您提供了快速调用数据服务API的基础SDK及示例调用代码。这里向您介绍如何使用Dataphin服务Java SDK。

Java SDK的代码文件层级结构如下:

重要

JAR包版本可能跟随SDK的升级而升级。

Java SDK/

  • demo/

    • CallApiDemo.java这里提供了同步API的调用示例和方法。

    • CallAsyncApiDemo.java这里提供了异步API的调用示例和方法。

  • lib/

    • dataphin-sdk-core-java-v5.2.0.jarSDK的依赖包。

    • dataphin-sdk-core-java-v5.2.0-javadoc.jar上述依赖包的Javadoc。

    • dataphin-sdk-core-java-v5.2.0-jar-with-dependencies.jar上述依赖包的全依赖包。

  • ApiDocument_v5.2.0.mdAPI接口文档。

  • LICENSE许可证。

Java SDK获取方式如下:

  1. Dataphin首页的顶部菜单栏,选择服务 > 调用

  2. 在左侧导航栏单击调用说明

  3. 单击API调用说明页签,在页面右上方选择Java SDK下载,将下载SDKJar包添加至pom.xml中。

Java SDK调用同步API流程

重要
  • 在调用API之前,您首先需要初始化客户端。

  • API的响应时间较长,可使用异步调用,在整个等待应答期间,主线程不会被阻塞。

  • 您可以实例化QueryParamRequest对象,并且设置请求参数满足不同的查询需要,详情请参考调用实例中的packRequestParam方法。

  • API请求和返回结果信息请查看SDK中的APIDocument.md。

  • 若在使用中遇到问题,请咨询Dataphin技术支持。

步骤一:环境准备

  1. Dataphin服务Java SDK适用于JDK 1.6及以上版本。

  2. 您需要准备一对授权密钥供SDK生成鉴权和签名信息,即AppKeyAppSecret。

    AppKeyAppSecret可在服务 > 调用 > 应用管理列表中获取。

    重要

    AppKeyAppSecretDataphin数据服务认证用户请求的密钥,这两个配置如果保存在客户端,请妥善加密。

  3. pom.xml中添加如下依赖,如果添加dataphin-sdk-core-java报错请手动添加该JAR文件,路径JAVA_SDK/lib/dataphin-sdk-core-java-v5.2.0.jar(即所获取Java SDK中的JAR包)。

    说明

    dataphin-sdk-core-java并不存在于中央Maven仓库,因此下载该SDK后还需要您上传至贵公司的Maven仓库,或者在IDEA、Eclipse中手动引入。

    <dependency>
        <groupId>com.alibaba.dt</groupId>
        <artifactId>dataphin-sdk-core-java</artifactId>
        <version>v5.2.0</version>
    </dependency>

步骤二:引入Java SDKAPI接口调用类

  1. 服务 > 市场 > API服务列表中下载对应的API文档。

  2. 导入CallApiDemo.java,修正CallApiDemo.java类的importpackage。

    /*
     * Copyright 2018 Alibaba.com All right reserved. This software is the confidential and proprietary
     * information of Alibaba.com ("Confidential Information"). You shall not disclose such Confidential
     * Information and shall use it only in accordance with the terms of the license agreement you
     * entered into with Alibaba.com.
     */
    import java.util.HashMap;
    import java.util.List;
    
    import com.alibaba.cloudapi.sdk.constant.SdkConstant;
    import com.alibaba.cloudapi.sdk.enums.Scheme;
    import com.alibaba.cloudapi.sdk.model.ApiResponse;
    import com.alibaba.dt.dataphin.client.ApiClient;
    import com.alibaba.dt.dataphin.client.ApiClientBuilderParams;
    import com.alibaba.dt.dataphin.schema.OrderBy;
    import com.alibaba.dt.dataphin.schema.QueryParamRequest;
    import com.alibaba.fastjson.JSONObject;
    
    import com.google.common.collect.Lists;
    import com.google.common.collect.Maps;
    
    import static com.alibaba.cloudapi.sdk.constant.SdkConstant.CLOUDAPI_LF;
    
    public class CallApiDemo {
    
        /**
         * 访问域名或ip,在数据服务的网络配置中获得该值
         */
        private static final String HOST = "xxx";
        /**
         * 应用appKey,即你用哪个APP来调用这个API
         */
        private static final String APP_KEY = "xxx";
        /**
         * 应用appSecret,即你用哪个APP来调用这个API
         */
        private static final String APP_SECRET = "xxx";
        /**
         * 配置调用的API编号
         */
        private static final String API_ID = "xxx";
    
        public static void main(String[] args) throws Exception {
            // 同步调用GET类型API
            syncGet();
            // 同步调用LIST类型API
            syncList();
            // 异步调用GET类型API
            asyncGet();
            // 异步调用LIST类型API
            asyncList();
        }
    
        public static void syncGet() throws Exception {
            // 获取 ApiClient 对象
            ApiClient client = getClient();
            // 需要按需修改里面的返回字段、查询条件等
            QueryParamRequest queryParamRequest = packRequestParam();
    
            ApiResponse response = client.getSync(API_ID, queryParamRequest);
            System.out.println(getResultString(response));
        }
    
        public static void syncList() throws Exception {
            // 获取 ApiClient 对象
            ApiClient client = getClient();
            // 需要按需修改里面的返回字段、查询条件等
            QueryParamRequest queryParamRequest = packRequestParam();
    
            ApiResponse response = client.listSync(API_ID, queryParamRequest);
            System.out.println(getResultString(response));
        }
    
        public static void asyncGet() throws Exception {
            // 获取 ApiClient 对象
            ApiClient client = getClient();
            // 需要按需修改里面的返回字段、查询条件等
            QueryParamRequest queryParamRequest = packRequestParam();
    
            client.getAsync(API_ID, queryParamRequest,
                    new ApiCallback() {
                        @Override
                        public void onFailure(ApiRequest request, Exception e) {
                            e.printStackTrace();
                        }
    
                        @Override
                        public void onResponse(ApiRequest request, ApiResponse response) {
                            try {
                                System.out.println(getResultString(response));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
            System.out.println("--- main线程提前结束 ---");
        }
    
        public static void asyncList() throws Exception {
            // 获取 ApiClient 对象
            ApiClient client = getClient();
            // 需要按需修改里面的返回字段、查询条件等
            QueryParamRequest queryParamRequest = packRequestParam();
    
            client.listAsync(API_ID, queryParamRequest,
                    new ApiCallback() {
                        @Override
                        public void onFailure(ApiRequest request, Exception e) {
                            e.printStackTrace();
                        }
    
                        @Override
                        public void onResponse(ApiRequest request, ApiResponse response) {
                            try {
                                System.out.println(getResultString(response));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
            System.out.println("--- main线程提前结束 ---");
        }
    
        private static ApiClient getClient() {
            ApiClientBuilderParams params = new ApiClientBuilderParams();
            // 应用appKey
            params.setAppKey(APP_KEY);
            // 应用appSecret
            params.setAppSecret(APP_SECRET);
            // 访问域名或ip
            params.setHost(HOST);
            // 默认为HTTP协议,如果API支持HTTPS,这里也可以设置HTTPS
            params.setScheme(Scheme.HTTP);
            // stage环境变量:PRE指定开发环境API、RELEASE指定生产环境API
            params.setStage("RELEASE");
            // 如果使用二级域名或未指定环境的独立域名,需要设置env
            // 有 PROD 和 PRE 两种值(如果是basic模式,传PROD; 如果是Dev-Prod模式,PROD表示查生产环境数据,PRE表示查开发环境数据)
            // 如果已经指定了访问环境的独立域名,则env参数不会起作用
            params.setEnv("PROD");
            return new ApiClient(params);
        }
    
        private static QueryParamRequest packRequestParam() {
            QueryParamRequest queryParamRequest = new QueryParamRequest();
    
            /********* API相关业务参数设置 begin *********/
            /*
             * 代理账号类型,非必填
             * 注意,若要使用代理模式,需同时满足以下条件:
             *  1. 开通行级权限功能
             *  2. 应用申请了代理权限
             *  3. API设置了关联的行级权限
             *
             * 当使用代理模式认证时,需要指定代理用户的账号类型。
             *  ACCOUNT_NAME:Dataphin的用户名。
             *  USER_ID:Dataphin内部的唯一ID。
             *  SOURCE_USER_ID:源系统账号ID。
             * 仅当设置了DelegationUid时,需要配置此参数。若未填写此参数,则默认类型为USER_ID。
             */
            queryParamRequest.setAccountType("USER_ID");
    
            /*
             * 代理账号ID,非必填
             * 被代理访问的用户,需根据所选AccountType的类型,传入对应账号ID。
             * 设置该参数且API设置了关联的行级权限规则,会使用代理模式的认证方式。
             */
            queryParamRequest.setDelegationUid("abcd");
    
            /*
             * 请求参数列表,非必填的参数可不传,必填参数必须传,否则会报错
             * 其中key为对应的查询字段,value为查询字段对应的值
             * 例如这里的id为请求字段名,1id对应的值,可以设置多个查询参数
             * 注意:如果是 IN 类型的参数,使用 List 包装参数值
             */
            HashMap<String, Object> conditions = Maps.newHashMap();
            conditions.put("id", 1);
            conditions.put("age", Lists.newArrayList(10,20,30));
            queryParamRequest.setConditions(conditions);
    
            /*
             * 返回参数列表,不能为空
             * 例如指定返回idname
             * 注意:返回参数如果不存在或没权限会报错
             */
            queryParamRequest.setReturnFields(Lists.newArrayList("id", "name"));
    
            /*
             * 排序字段,非必填
             * 注意oraclesqlServer使用分页需要同时使用排序
             * 指定参数升序或者降序,可设置多个字段进行升序或者降序
             * 例如返回结果按id进行升序
             */
            List<OrderBy> orderList = Lists.newArrayList();
            orderList.add(new OrderBy("id1", OrderBy.Order.ASC));
            orderList.add(new OrderBy("id2", OrderBy.Order.DESC));
            queryParamRequest.setOrderBys(orderList);
    
            /*
             * 分页参数,非必填,仅LIST类型API生效
             */
            // 从第几条数据取
            queryParamRequest.setPageStart(0);
            // 每页取多少条数据
            queryParamRequest.setPageSize(10);
    
            /*
             * API版本号,非必填,仅开发环境支持设置
             */
            queryParamRequest.setApiVersion("V1");
    
            /********* API相关业务参数设置 end *********/
    
    
    
            /********* 功能参数设置 begin *********/
    
            /*
             * 是否使用模型缓存
             * 开启会减少同一个服务单元API相同出入参时的解析频次,提高查询效率
             */
            queryParamRequest.setUseModelCache(Boolean.getBoolean("false"));
    
            /*
             * 是否使用结果缓存
             * 开启则会缓存同一个API相同条件、相同返回字段的查询结果
             * 适用于数据不变化的查询,减少相同SQL的查询频次,提高查询效率
             * 缓存时长默认30分钟,3.5.6 版本后,在API开发页面可设置缓存时长
             * 注意:如果API未开启结果缓存,该参数无效
             */
            queryParamRequest.setUseResultCache(Boolean.getBoolean("false"));
    
            /*
             * 是否保持字段的大小写格式
             * 如果对大小写敏感,建议设置为true
             * 为false时,直连API返回结果的字段名默认为大写字母
             */
            queryParamRequest.setKeepColumnCase(true);
    
            /********* 功能参数设置 end *********/
    
            return queryParamRequest;
        }
    
        private static String getResultString(ApiResponse response) {
            StringBuilder result = new StringBuilder();
            result.append("ResultCode:").append(CLOUDAPI_LF).append(response.getCode()).append(CLOUDAPI_LF);
            result.append("RequestId:").append(response.getHeaders().get("x-ca-request-id")).append(CLOUDAPI_LF);
            result.append("ErrorCode:").append(response.getHeaders().get("x-ca-error-code")).append(CLOUDAPI_LF);
            if (200 != response.getCode()) {
                result.append("Error:").append(response.getHeaders().get("x-ca-error-message")).append(CLOUDAPI_LF);
            }
    
            result.append("ResultBody:").append(CLOUDAPI_LF).append(new String(response.getBody(), SdkConstant.CLOUDAPI_ENCODING));
            return result.toString();
        }

步骤三:初始化通信通道类

要调用API,首先要初始化客户端。您可以参考ClientDemo.java中的示例代码,使用对应的ApiClientBuilderParams类来进行初始化。其中,需要把Host、APP_KeyAPP_Secret三个变量替换为用户的真实数据。

步骤四:API接口说明

  • API接口类型

    API接口类型分为LISTGET,LIST支持分页查询而GET不支持,请参考CallApiDemo.java中的packRequestParam方法, 设置QueryParamRequest里的参数。

  • 调用API接口

    • SDK中的LISTGET方法为Dataphin数据服务的通用方法,SDK中提供同步和异步的调用方法。在调用API之前,您需要根据您在Dataphin数据服务中定义的API填入相关的请求参数。

    • 调试用例中condition为业务请求参数,returnFieldsAPI的返回参数,具体参数请参考服务 > 调用 > 已授权API服务页面,单击目标API操作列下调试,进入调试页面。

    • 请求参数中的API_ID,请参考服务 > 调用 > 已授权API服务页面API列下的API_ID。

Java SDK调用异步API流程

重要
  • 在调用API之前,您首先需要初始化客户端。

  • API的响应时间较长,可使用异步调用,在整个等待应答期间,主线程不会被阻塞。

  • 您可以实例化QueryParamRequest对象,并且设置请求参数满足不同的查询需要,详情请参考调用实例中的packRequestParam方法。

  • API请求和返回结果信息请查看SDK中的APIDocument.md。

  • 若在使用中遇到问题,请咨询Dataphin技术支持。

步骤一:环境准备

  1. Dataphin服务Java SDK适用于JDK 1.6及以上版本。

  2. 您需要准备一对授权密钥供SDK生成鉴权和签名信息,即AppKeyAppSecret。

    AppKeyAppSecret可在服务 > 调用 > 应用管理列表中获取。

    重要

    AppKeyAppSecretDataphin服务认证用户请求的密钥,这两个配置如果保存在客户端,请妥善加密。

  3. pom.xml中添加如下依赖,如果添加dataphin-sdk-core-java报错请手动添加该jar文件,路径JAVA_SDK/lib/dataphin-sdk-core-java-v5.2.0.jar(即所获取Java SDK中的Jar包)。

    说明

    dataphin-sdk-core-java并不存在于中央Maven仓库,因此下载该SDK后还需要您上传至贵公司的Maven仓库,或者在IDEA、Eclipse中手动引入。

    <dependency>
        <groupId>com.alibaba.dt</groupId>
        <artifactId>dataphin-sdk-core-java</artifactId>
        <version>v5.2.0</version>
    </dependency>

步骤二:引入Java SDKAPI接口调用类

  1. 服务 > 市场 > API服务列表中下载对应的API文档。

  2. 导入CallAsyncApiDemo.java,修正CallAsyncApiDemo.java类的importpackage。

    /*
     * Copyright 2018 Alibaba.com All right reserved. This software is the confidential and proprietary
     * information of Alibaba.com ("Confidential Information"). You shall not disclose such Confidential
     * Information and shall use it only in accordance with the terms of the license agreement you
     * entered into with Alibaba.com.
     */
    import com.alibaba.cloudapi.sdk.enums.Scheme;
    import com.alibaba.cloudapi.sdk.model.ApiRequest;
    import com.alibaba.dt.dataphin.client.ApiClientBuilderParams;
    import com.alibaba.dt.dataphin.client.DataphinDataServiceException;
    import com.alibaba.dt.dataphin.client.async.AsyncApiCallBack;
    import com.alibaba.dt.dataphin.client.async.AsyncApiClient;
    import com.alibaba.dt.dataphin.client.async.AsyncJobContext;
    import com.alibaba.dt.dataphin.schema.AsyncQueryResults;
    import com.alibaba.dt.dataphin.schema.OrderBy;
    import com.alibaba.dt.dataphin.schema.QueryParamRequest;
    import com.alibaba.fastjson.JSONObject;
    import com.google.common.base.Splitter;
    import com.google.common.collect.Lists;
    import com.google.common.collect.Maps;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    
    public class CallAsyncApiDemo {
    
        /**
         * 访问域名或ip,在数据服务的网络配置中获得该值
         */
        private static final String HOST = "xxx";
        /**
         * 应用appKey,即你用哪个APP来调用这个API
         */
        private static final String APP_KEY = "xxx";
        /**
         * 应用appSecret,即你用哪个APP来调用这个API
         */
        private static final String APP_SECRET = "xxx";
        /**
         * 配置调用的API编号
         */
        private static final String API_ID = "xxx";
        /**
         * 每批次查询条数,默认1000条
         */
        private static final Integer FETCH_SIZE = 1000;
    
        public static void main(String[] args) throws Exception {
            //  阻塞式调用
            callAsyncApiBlock();
            //  非阻塞式调用
            callAsyncApiNotBlock();
        }
    
        /**
         * 阻塞式调用
         */
        @SuppressWarnings("all")
        private static void callAsyncApiBlock() {
    
            // 获取 AsyncApiClient 对象
            AsyncApiClient asyncApiClient = getClient();
    
            // 需要按需修改里面的返回字段、查询条件等
            QueryParamRequest queryParamRequest = packRequestParam();
    
            AsyncQueryResults asyncQueryResults = asyncApiClient.listAsyncWaitFinish(API_ID, queryParamRequest);
    
            System.out.println(JSONObject.toJSONString(asyncQueryResults));
    
            // 关闭客户端,回收资源
            asyncApiClient.shutdown();
        }
    
        /**
         * 非阻塞式调用
         */
        @SuppressWarnings("all")
        private static void callAsyncApiNotBlock(){
    
            // 获取 AsyncApiClient 对象
            AsyncApiClient asyncApiClient = getClient();
    
            // 需要按需修改里面的返回字段、查询条件等
            QueryParamRequest queryParamRequest = packRequestParam();
    
            try {
                AsyncApiCallBack callback = new AsyncApiCallBack() {
                    @Override
                    public void onFailure(ApiRequest request, DataphinDataServiceException e) {
                        System.out.println(e.getMessage());
                    }
    
                    @Override
                    public void onResponse(ApiRequest request, AsyncQueryResults results) {
                        System.out.println(JSONObject.toJSONString(results));
                    }
                };
    
                AsyncJobContext context = asyncApiClient.listAsync(API_ID, queryParamRequest, callback);
    
                // 请求成功会返回本次请求的jobId
                System.out.printf("jobId: %s", context.getJobId());
    
                // 等待运行结束,真实场景请勿使用sleep方式等待
                Thread.sleep(600000);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            // 关闭客户端,回收资源
            asyncApiClient.shutdown();
        }
    
        private static AsyncApiClient getClient() {
            ApiClientBuilderParams params = new ApiClientBuilderParams();
            // 应用appKey
            params.setAppKey(appKey);
            // 应用appSecret
            params.setAppSecret(appSecret);
            // 访问域名或ip
            params.setHost(HOST);
            // 默认为http协议, 可根据API设置https协议
            // 注意:Dataphin内置网关不支持https,阿里云API网关支持https
            params.setScheme(Scheme.HTTP);
            // 每批次查询条数,默认1000条
            params.setFetchSize(FETCH_SIZE);
            // stage环境变量:PRE指定开发环境API、RELEASE指定生产环境API
            params.setStage("RELEASE");
            // 如果使用二级域名或未指定环境的独立域名,需要设置env
            // 有 PROD 和 PRE 两种值(如果是basic模式,传PROD; 如果是Dev-Prod模式,PROD表示查生产环境数据,PRE表示查开发环境数据)
            // 如果已经指定了访问环境的独立域名,则env参数不会起作用
            params.setEnv("PROD");
            return new AsyncApiClient(params);
        }
    
        private static QueryParamRequest packRequestParam() {
            QueryParamRequest queryParamRequest = new QueryParamRequest();
    
            /********* API相关业务参数设置 begin *********/
            /*
             * 代理账号类型,非必填
             * 注意,若要使用代理模式,需同时满足以下条件:
             *  1. 开通行级权限功能
             *  2. 应用申请了代理权限
             *  3. API设置了关联的行级权限
             *
             * 当使用代理模式认证时,需要指定代理用户的账号类型。
             *  ACCOUNT_NAME:Dataphin的用户名。
             *  USER_ID:Dataphin内部的唯一ID。
             *  SOURCE_USER_ID:源系统账号ID。
             * 仅当设置了DelegationUid时,需要配置此参数。若未填写此参数,则默认类型为USER_ID。
             */
            queryParamRequest.setAccountType("USER_ID");
    
            /*
             * 代理账号ID,非必填
             * 被代理访问的用户,需根据所选AccountType的类型,传入对应账号ID。
             * 设置该参数且API设置了关联的行级权限规则,会使用代理模式的认证方式。
             */
            queryParamRequest.setDelegationUid("abcd");
    
            /*
             * 请求参数列表,非必填参数可不传,必填参数必须传,否则会报错
             * 其中key为对应的查询字段,value为查询字段对应的值
             * 例如这里的id为请求字段名,1id对应的值,可以设置多个查询参数
             * 注意:如果是 IN 类型的参数,使用 List 包装参数值,例如这里的age
             */
            HashMap<String, Object> conditions = Maps.newHashMap();
            conditions.put("id", 1);
            conditions.put("age", Lists.newArrayList(10,20,30));
            queryParamRequest.setConditions(conditions);
    
            /*
             * 返回参数列表,必填
             * 例如指定返回idname
             * 注意:返回参数如果不存在或没权限会报错
             */
            queryParamRequest.setReturnFields(Lists.newArrayList("id", "name"));
    
            /*
             * 排序字段,非必填
             * 注意oraclesqlServer使用分页需要同时使用排序
             * 指定参数升序或者降序,可设置多个字段进行升序或者降序
             * 例如返回结果按id进行升序
             */
            List<OrderBy> orderList = Lists.newArrayList();
            orderList.add(new OrderBy("id1", OrderBy.Order.ASC));
            orderList.add(new OrderBy("id2", OrderBy.Order.DESC));
            queryParamRequest.setOrderBys(orderList);
    
            /*
             * API版本号,非必填,仅开发环境支持设置
             */
            queryParamRequest.setApiVersion("V1");
    
            /********* API相关业务参数设置 end *********/
    
    
            /********* 功能参数设置 begin *********/
    
            /*
             * 是否保持字段的大小写格式,固定传true
             */
            queryParamRequest.setKeepColumnCase(true);
    
            /********* 功能参数设置 end *********/
    
            return queryParamRequest;
        }
    }

步骤三:初始化通信通道类

要调用API,首先要初始化客户端。您可以参考CallAsyncApiDemo.java中的示例代码,使用对应的ApiClientBuilderParams类来进行初始化。其中,需把Host、APP_KeyAPP_Secret三个变量替换为用户的真实数据。

步骤四:API接口说明

  • API接口类型

    API接口类型分为LISTGET,LIST支持分页查询而GET不支持,请参考CallAsyncApiDemo.java中的packRequestParam方法, 设置QueryParamRequest里的参数。

  • 调用API接口

    • SDK中的LISTGET方法为Dataphin数据服务的通用方法,SDK中同时提供同步和异步的调用方法。在调用API之前,您需要根据您在Dataphin数据服务定义的API填写相关的请求参数。

    • 调试用例中condition为业务请求参数,returnFieldsAPI的返回参数,具体参数请参考服务 > 调用 > 已授权API服务页面,单击目标API操作列下调试,进入调试页面。

    • 请求参数中的API_ID,请参考服务 > 调用 > 已授权API服务页面API列下的API_ID。

Python SDK调用流程

步骤一:环境准备

  1. Python SDK适用于Python3.9及以上版本。

    Python SDK获取方式如下:

    1. Dataphin首页的顶部菜单栏,选择服务 > 调用

    2. 在左侧导航栏单击调用说明

    3. 单击API调用示例页签,单击页面右上方的python调用示例下载按钮,获取Python SDK core包。

  2. 准备一对授权密钥供SDK生成鉴权和签名信息,即AppKeyAppSecret。

    重要

    AppKeyAppSecretDataphin服务认证用户请求的密钥,这两个配置如果保存在客户端,请妥善加密。

  3. 准备一个JSON文件,格式如下:

    {
      "host": "API网关域名",
      "port": 80,
      "impalaConfig": {
        "pollingTimeout": 300,
        "pollingInterval": 800
      },
      "applicationConfig": {
        "appKey": "敏感数据自行填充",
        "appSecret": "敏感数据自行填充"
      },
      "apiConfig": {
        "apiNo": 10008,
        "scheme": "HTTP",
        "stage": "RELEASE",
        "env": "PROD",
        "method": "LIST",
        "queryParamRequest": {
          "conditions": {"id": "1"}, // 请求参数列表,根据参数决定,非必填参数可不传,必填参数必须传
          "returnFields": ["id", "name", "age"], // 返回参数列表,必填,返回参数如果不存在或没权限会报错
          "orderBys": [{"field": "id", "order": "ASC"}], // 排序字段,非必填
          "useModelCache": "false", // 是否使用模型缓存,开启会减少同一个服务单元API相同出入参时的解析频次,提高查询效率
          "useResultCache": "false", // 是否使用结果缓存,开启则会缓存同一个API相同条件、相同返回字段的查询结果
          "apiVersion": "V1", // API版本号,非必填,仅开发环境支持设置
          "accountType": "USER_ID", // 代理账号类型,非必填,使用代理模式时需要配置此参数
          "delegationUid": "abcd" // 代理账号ID,非必填,使用代理模式时需要配置此参数
        }
      }
    }

步骤二:部署Python SDK

  1. 安装Python开发工具PyCharm。

  2. 打开Python项目。

  3. Demo类的启动参数上配置JSON文件路径。

  4. 具体调用请参照demo.py。

步骤三:调用API

  1. JSON文件中配置调用参数信息。

  2. Python SDK通过读取JSON文件来组装API调用的基础参数。

  3. 调用apiClient.callApi方法,具体参照demo.py。

    # -*- coding: utf-8 -*-
    import dataapi
    import sys
    
    with open(str(sys.argv[1]), encoding="utf-8") as f:
        json_obj = eval(f.read().replace('\n\u200b', ''))
    # 这里是读取上下文的json文件,假如不需要json文件的话,直接填写对应值的就好了
    
    # 网关调用地址
    host = json_obj["host"]
    # 网关调用端口
    port = json_obj["port"]
    # 可不配置。只对impala类型的API有效,轮询超时时间
    pollingTimeout = json_obj["impalaConfig"]["pollingTimeout"]
    # 可不配置。只对impala类型的API有效,轮询间隔
    pollingInterval = json_obj["impalaConfig"]["pollingInterval"]
    # app的信息,你用哪个APP来调用这个API
    appKey = json_obj["applicationConfig"]["appKey"]
    appSecret = json_obj["applicationConfig"]["appSecret"]
    # api的信息
    apiId = json_obj["apiConfig"]["apiNo"]
    # 用什么方式调用API? 值是:HTTP 或 HTTPS。注意私有网关只支持HTTP   【区分大小写】
    scheme = json_obj["apiConfig"]["scheme"]
    # 生产环境:RELEASE,开发环境:PRE
    stage = json_obj["apiConfig"]["stage"]
    # 有 PROD 和 PRE 两种值 (如果是basic模式,传死PROD; 如果是Dev-Prod模式,PROD表示查生产库,PRE表示查开发库   【区分大小写】
    env = json_obj["apiConfig"]["env"]
    # 请求参数,必填
    queryParam = json_obj["apiConfig"]["queryParamRequest"]
    
    # API是 GET 还是 LIST?  【区分大小写】
    method = json_obj["apiConfig"]["method"]
    
    if (host == None or host == ""):
        raise Exception("host信息缺失")
    
    if (appKey == None or appKey == ""):
        raise Exception("appKey信息缺失")
    
    if (appSecret == None or appSecret == ""):
        raise Exception("appSecret信息缺失")
    
    if (method == None or method == ""):
        raise Exception("method信息缺失")
    
    if (apiId == None or apiId == ""):
        raise Exception("apiNo信息缺失")
    
    # 配置impala
    impalaConfig = dataapi.ImpalaConfig(pollingTimeout=pollingTimeout, pollingInterval=pollingInterval)
    # 配置app
    appConfig = dataapi.AppConfig(appKey=appKey, appSecret=appSecret)
    apiConfig = dataapi.ApiConfig(apiId, scheme, stage, env, queryParam, method)
    myConfig = dataapi.MyConfig(host, port, impalaConfig, appConfig, apiConfig)
    
    apiClient = dataapi.ApiClient(myConfig)
    
    # 同步API请求
    resp = apiClient.callApi(queryParam)
    print(resp)
    
    # 异步API请求
    asyncResp = apiClient.asyncCallApi(queryParam)
    print(asyncResp)

白名单调用方式(仅私有化部署时支持)

通过配置白名单免密方式访问API的安全策略,可简化API调用流程。IP白名单策略为应用级别策略,目前仅私有云支持此方式调用。

开发流程

步骤一:后台配置

您需要在数据服务中创建API、应用、应用白名单以及将应用和API进行绑定,才能通过白名单方式访问API。

  • 创建API:您可在服务 > 开发 > API页面,选择通过直连数据源模式、逻辑表API-SQL模式、逻辑表API-向导模式、注册API和组合API五种方式创建API,如何创建,请参见创建API

  • 创建应用及应用白名单:应用可用于调用生产环境的API,并可为API设置白名单,如何创建应用及白名单,请参见新建及管理服务应用

  • 应用和API绑定:需申请该API的所属应用权限才能使用该API,如何申请,请参见管理API权限

步骤二:发起请求

  1. 请求类型:POST

    只支持POST提交的请求,BODY一律使用JSON字符串,并且Content-Type设置为application/octet-stream; charset=utf-8

  2. 设置公共入参

    参数名

    位置

    是否必填

    示例

    说明

    accept

    Header

    application/json; charset=utf-8

    响应格式。

    host

    Header

    7229fc4974**

    -cn-shanghai.alicloudapi.com。

    x-ca-key

    Header

    2037**895

    appkey,调用API的身份标识。

    x-ca-stage

    Header

    RELEASE

    环境标识,RELEASE访问生产环境、PRE访问开发环境。

    Content-Type

    Header

    application/octet-stream; charset=utf-8

    请求格式。

    whitelist-flag

    Header

    1

    白名单标识(非空)。

  3. 请求格式

    • URL:POST [host]/method/apiId?appKey=应用的AppKey&env=PROD

      • host:API网关域名(可在服务 > 管理 > 网络配置页面获取)。

      • method:API的请求方式,GET或者LIST(可在服务 > 调用> 已授权API服务 > 调试页面获取)。

      • apiId:API的唯一标识(可在服务 > 调用> 已授权API服务 > 调试页面获取)。

      • appKey:该API绑定的应用的唯一标识(可在服务 > 调用 > 应用管理页面获取)

      • env:环境标识,PROD表示访问生产环境上的API,PRE表示访问开发环境的API。

      请求URL示例:gateway.aliyun.com/list/12345?appKey=xxx&env=PROD

  4. 使用PostMan调用示例

    1. 步骤一:请求地址

      请求POST地址[host]/method/apiId?appKey=应用的AppKey&env=PROD

    2. 步骤二:填入Header

      填入Header,可参考设置公共入参填写。

      Header示例如下:

      accept:application/json;charset=utf-8
      x-ca-key:敏感数据自行填充
      host:API网关域名
      x-ca-stage:RELEASE
      Content-Type:application/octet-stream;charset=utf-8
      whitelist-flag:1
    3. 步骤三:填入body

      说明

      Content-Type使用application/octet-stream; charset=utf-8

      body示例:

      {
        "conditions": {"id": "1"}, // 请求参数列表,根据参数决定,非必填参数可不传,必填参数必须传
        "returnFields": ["id", "name", "age"], // 返回参数列表,必填,返回参数如果不存在或没权限会报错
        "orderBys": [{"field": "id", "order": "ASC"}], // 排序字段,非必填
        "useModelCache": "false", // 是否使用模型缓存,开启会减少同一个服务单元API相同出入参时的解析频次,提高查询效率
        "useResultCache": "false", // 是否使用结果缓存,开启则会缓存同一个API相同条件、相同返回字段的查询结果
        "apiVersion": "V1", // API版本号,非必填,仅开发环境支持设置
        "accountType": "USER_ID", // 代理账号类型,非必填,使用代理模式时需要配置此参数
        "delegationUid": "abcd" // 代理账号ID,非必填,使用代理模式时需要配置此参数
      }

错误码

客户端错误

错误代码

HTTP状态码

语义

解决方案

Throttled by APP Flow Control

403

APP流控被限制

调用频率过高导致被流控,可以联系服务提供方放宽限制。

Throttled by API Flow Control

403

API流控被限制

调用频率过高导致被流控,可以联系服务提供方放宽限制。

Throttled by DOMAIN Flow Control

403

因二级域名流控被限制

直接访问二级域名调用API,每天被访问次数上限1000次。

TThrottled by GROUP Flow Control

403

因分组流控被限制

调用频率过高导致被流控,可以联系服务提供方放宽限制。

Empty Request Body

400

body为空

请检查请求Body内容。

Invalid Request Body

400

body无效

请检查请求Body。

Invalid Param Location

400

参数位置错误

请求参数位置错误。

Invalid Url

400

URL无效

请求的Method、Path或者环境不对。请参照错误说明Invalid URL。

Invalid Domain

400

域名无效

请求域名无效,根据域名找不到API。请联系 Dataphin服务团队。

Invalid HttpMethod

400

HttpMethod无效

输入的Method不合法。

Invalid AppKey

400

AppKey无效或不存在

请检查传入的AppKey。注意左右空格的影响。

Invalid AppSecret

400

APPSecret错误

检查传入的AppSecret。注意左右空格的影响。

Timestamp Expired

400

时间戳过时

请核对请求系统时间是否为标准时间。

Invalid Timestamp

400

时间戳不合法

请参照请求签名说明文档。

Empty Signature

404

签名为空

请传入签名字符串,请参照请求签名说明文档。

Invalid Signature, Server StringToSign:%s

400

签名无效

签名无效,参照Invalid Signature错误说明。

Invalid Content-MD5

400

Content-MD5值不合法

请求Body为空,但传入了MD5值,或 MD5 值计算错误。请参照请求签名说明文档。

Unauthorized

403

未被授权

APP未获得要调用的API的授权。请参照错误说明Unauthorized。

Nonce Used

400

SignatureNonce已被使用

x-ca-nonce不能被重复使用,重新生成x-ca-nonce。

API Not Found

400

找不到API

传入的API请求地址或者HttpMethod不正确,或已下线。

服务器端错误(调用 API)

以下为API服务端错误。

错误代码

HTTP状态码

语义

解决方案

Internal Error

500

内部错误

建议重试。

Failed To Invoke Backend Service

500

底层服务错误

API底层服务错误,建议重试。

Service Unavailable

503

服务不可用

建议重试。

Async Service

504

服务超时

建议重试。

服务器端错误(执行SQL语句)

错误代码

语义

DPN-OLTP-COMMON-000

成功。

DPN.Oltp.Common.Running

运行中。

DPN-OLTP-COMMON-001

系统发生未知异常。

DPN-OLTP-COMMON-002

参数异常。

DPN-OLTP-COMMON-003

不支持。

DPN-OLTP-COMMON-004

SQL解析异常。

DPN-OLTP-COMMON-005

SQL注入检测未通过。

DPN-OLTP-ENGINE-000

查询超时。

DPN-OLTP-ENGINE-001

参数错误。

DPN-OLTP-ENGINE-002

对象找不到。

DPN-OLTP-ENGINE-003

不支持。

DPN-OLTP-ENGINE-004

通信表错误。

DPN-OLTP-ENGINE-005

SQL解析失败。

DPN-OLTP-ENGINE-006

元数据错误。

DPN-OLTP-ENGINE-007

参数处理错误。

DPN-OLTP-ENGINE-008

构建执行模型错误。

DPN-OLTP-ENGINE-009

执行失败。

DPN-OLTP-ENGINE-010

数据源错误。

DPN-OLTP-ENGINE-011

HBase引擎不支持。

DPN-OLTP-ENGINE-012

对象序列化失败。

DPN-OLTP-ENGINE-013

权限校验失败。

DPN-OLTP-ENGINE-014

Elasticsearch引擎不支持。

DPN-OLTP-ENGINE-015

MongoDB引擎不支持。

DPN-OLTP-ENGINE-016

字段类型错误。

DPN-OLTP-ENGINE-017

Redis缓存异常。

DPN-OLTP-ENGINE-018

跨数据源不支持。

DPN-OLTP-ENGINE-018-01

跨数据源不支持Group by。

DPN-OLTP-ENGINE-018-02

跨数据源不支持Order by。

DPN-OLTP-ENGINE-018-03

跨数据源不支持没有where条件。

DPN-OLTP-ENGINE-018-04

跨数据源不支持page start不等于0。

DPN-OLTP-ENGINE-018-05

跨数据源不支持在where条件中存在or操作。

DPN-OLTP-ENGINE-018-06

跨数据源不支持在一个select item中有来自多个物理表的字段。

DPN-OLTP-ENGINE-018-07

跨数据源查询必须所有的主键都在。

DPN-OLTP-ENGINE-019

数据类型编码或者参数类型转换失败。

DPN-OLTP-ENGINE-20

熔断。

DPN-OLTP-ENGINE-21

限流。

DPN-OLTP-ENGINE-22

查询超时。

DPN-OLTP-ENGINE-23

组合API的子API异常。

DPN-OLTP-ENGINE-24

无代理权限。

DPN.Oltp.Auth

权限校验失败。

DPN.Oltp.Async.JobNotExists

异步API任务不存在。

DPN.Oltp.Async.JobStatusNotSupport

异步API任务状态不支持该操作。

DPN.Oltp.Async.GetResultError

异步API获取结果失败。

DPN.Oltp.Oltp.JsonContentParseError

JSON内容解析失败。

DPN.Oltp.Oltp.HttpRequestError

HTTP请求失败。

DPN.Oltp.Jdbc.ProjectForbidden

无权修改该项目下的表。

DPN-OLTP-JDBC-001

请求头丢失Session。

DPN-OLTP-JDBC-002

Session错误。

DPN-OLTP-JDBC-003

无权访问数据库。

DPN-OLTP-JDBC-004

无权访问数据表。

DPN-OLTP-JDBC-005

AccountId错误。

DPN-OLTP-JDBC-006

终止查询。

DPN-OLTP-OLAP-001

Olap客户端查询数据源失败。

DPN-OLTP-OLAP-002

Olap客户端运行失败。

DPN.Oltp.Olap.SessionError

OlapSession错误。

DPN.Oltp.Olap.SessionNotFound

OlapSession不存在。

常见问题

问题:调用API404 回答

  • 如果绑定了独立域名,请检查是HTTP协议还是HTTPS协议。

  • 检查调用的API创建的类型是LIST还是GET,因为LIST/GET会作为URL的一部分。

  • 检查API是否发布到对应的环境。

     public static ApiClient getClient() {
          if (apiClient == null) {
              synchronized (ClientDemo.class) {
                  if (apiClient == null) {
                      ...
                      params.setStage("RELEASE");
                      params.setEnv("PROD");
                      apiClient = new ApiClient(params);
                      return apiClient;
                  }
              }
     }

问题:调用API400 回答

  • 请检查x-ca-timestamp是否在15分钟的有效期内,x-ca-nonce15分钟内是否被重复使用,建议每次请求API,x-ca-timestamp取当前时间,x-ca-nonce新生成可以用UUID生成,作为唯一标识,没有格式要求。

  • 检查使用AppKey、AppSecret是否前后有空格。

  • 检查调用的API是否已授权,并且授权的APPSecretAppKey是否和下面参数private static final String APP_KEYprivate static final String APP_SECRET一致,不一致情况下出现400错误。

  • 注意检查客户端的签名值是否多加了空格,传给服务端的没有加(Invalid Signature),检查stringToSign中的值是否有空格,如客户端签名Content-Type:application/octet-stream; charset=utf-8有空格,但是传给服务端的没有空格Content-Type:application/octet-stream;charset=utf-8,就会报错Invalid Signature

问题:调用API403

回答:可能的原因:①调用协议与实际配置不匹配,②AppKeyAppSecret不正确。

  • 检查API配置的调用协议是HTTP还是HTTPS,在代码中设置为对应的参数。

    public static ApiClient getClient() {
          if (apiClient == null) {
              synchronized (ClientDemo.class) {
                  if (apiClient == null) {
                      ... 
                      //默认为http协议, 可设置https协议(os网关不支持https!!,非os网关可以支持https,具体决定于所调用的API)
                      // 这里
                      params.setScheme(Scheme.HTTP);
                        // 或
                      params.setScheme(Scheme.HTTPS);
                      ...
                  }
              }
          }
          return apiClient;
      }
  • 检查AppKeyAppSecret是否正确。

问题:调用API报错:return fields missing in param

回答:在packRequestParamListSyncpackRequestParamGetSync(根据APIGETLIST类型)方法中,按照下方脚本设置参数。

ArrayList<String> returnFiles = Lists.newArrayList("api的返回字段1","api的返回字段2",..."api的返回字段n");
queryParamRequest.setReturnFields(returnFiles);

问题:如何使用operatorIN的参数

回答:在SDK调用时,IN类型的参数需要使用LIST传递参数值,例如:

  • 假设参数名为p1,参数类型为StringDate,参数值为a、b、c,则应按下面方式设置参数:

HashMap<String, Object> condition = Maps.newHashMap();
condition.put("p1",Lists.newArrayList("a", "b", "c"));
  • 如果是数值类型,参数值为1、2、3,则应按下面方式设置参数:

HashMap<String, Object> condition = Maps.newHashMap();
condition.put("p1",Lists.newArrayList(1,2,3));

问题:使用SDK分页获取数据时,数据总数正确,但存在重复数据

原因:API代码中未使用排序字段使每次的排序结果唯一,或数据库本身不支持排序,导致每次分页获取数据时的查询结果的排序不一致,导致重复获取数据或丢失数据。

回答:确保返回结果排序的稳定性。若有主键,可增加主键字段排序,如果没有主键,可使用多个字段组成联合主键排序,确保每次排序的结果是稳定的。