API可使用SDK调用方式(包括Java SDK和Python SDK)及白名单免密调用方式。其中仅使用私有网关的时候支持白名单方式。本篇API调用示例为调用模板,您可根据模板配置API的调用示例。
SDK调用
Java SDK简介
Dataphin数据服务Java SDK为您提供了快速调用数据服务API的基础SDK及示例调用代码。这里向您介绍如何使用Dataphin服务Java SDK。
Java SDK的代码文件层级结构如下:
JAR包版本可能跟随SDK的升级而升级。
Java SDK/
demo/
ClientDemo.java提供了同步API的调用示例和方法。AsyncClientDemo.java提供了异步API的调用示例和方法。
lib/
dataphin-sdk-core-java-v5.4.0.jar本SDK的依赖包。dataphin-sdk-core-java-v5.4.0-javadoc.jar上述依赖包的Javadoc。dataphin-sdk-core-java-v5.4.0-jar-with-dependencies.jar上述依赖包的全依赖包。
ApiDocument_v5.4.0.mdAPI接口文档。LICENSE许可证。
Java SDK获取方式如下:
在Dataphin首页的顶部菜单栏,选择服务 > 应用管理。
在左侧导航栏单击调用说明。
单击API调用说明页签,在页面右上方选择Java SDK下载,将下载SDK的Jar包添加至pom.xml中。
Java SDK调用同步API流程
在调用API之前,您首先需要初始化客户端。
若API的响应时间较长,可使用异步调用,在整个等待应答期间,主线程不会被阻塞。
您可以实例化
QueryParamRequest对象,并且设置请求参数满足不同的查询需要,详情请参考调用实例中的packRequestParam方法。API请求和返回结果信息请查看SDK中的
APIDocument.md。若在使用中遇到问题,请咨询Dataphin技术支持。
步骤一:环境准备
Dataphin服务Java SDK适用于JDK 1.8及以上版本。
您需要准备一对授权密钥供SDK生成鉴权和签名信息,即AppKey和AppSecret。
AppKey和AppSecret可在服务 > 应用管理 > 我的应用列表中获取。
重要AppKey和AppSecret是Dataphin数据服务认证用户请求的密钥,这两个配置如果保存在客户端,请妥善加密。
在
pom.xml中添加如下依赖,如果添加dataphin-sdk-core-java报错请手动添加该JAR文件,路径JAVA_SDK/lib/dataphin-sdk-core-java-v5.4.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.4.0</version> </dependency>
步骤二:引入Java SDK的API接口调用类
在服务 > API市场 > API列表中下载对应的API文档。
导入ClientDemo.java,修正
ClientDemo.java类的import和package。import java.util.*; import java.util.function.Consumer; import com.alibaba.cloudapi.sdk.constant.SdkConstant; import com.alibaba.cloudapi.sdk.enums.Scheme; import com.alibaba.cloudapi.sdk.model.ApiCallback; import com.alibaba.cloudapi.sdk.model.ApiRequest; 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.client.sse.SseApiClient; import com.alibaba.dt.dataphin.schema.ManipulationParamRequest; import com.alibaba.dt.dataphin.schema.OrderBy; import com.alibaba.dt.dataphin.schema.QueryParamRequest; import com.alibaba.fastjson.JSON; /** * 同步API示例 * <p> * 使用方式: * 先配置好 HOST/APP_KEY/APP_SECRET/API_ID, * 再按需设置 getClient() 中的变量以及 packQueryParamRequest() 中的参数值。 * 注意: * getClient() 中的参数可能会因不同的 API 而设置不同的值,可以将 getClient() 改造成带有入参,以适应不同 API 使用不同的参数。 */ public class ClientDemo { /** * 访问域名或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(); // 流式调用GET类型API fluxGet(); // 分页查询的api,同时获取查询总数 syncListWithTotalNum(); // 同步调用Create类型API syncCreate(); // 同步调用Update类型API syncUpdate(); // 同步调用Delete类型API syncDelete(); } private static void syncListWithTotalNum() { ApiClient client = getClient(); // 需要按需修改里面的返回字段、查询条件等 QueryParamRequest queryParamRequest = packRequestParamWithReturnNum(); ApiResponse response = client.listSync(API_ID, queryParamRequest); String resultStr = getResultString(response); // contain totalNum in ResultBody System.out.println(resultStr); } /** * 同步调用GET类型API */ public static void syncGet() { // 获取 ApiClient 对象 ApiClient client = getClient(); // 需要按需修改里面的返回字段、查询条件等 QueryParamRequest queryParamRequest = packRequestParam(); ApiResponse response = client.getSync(API_ID, queryParamRequest); System.out.println(getResultString(response)); } /** * 同步调用LIST类型API */ public static void syncList() { // 获取 ApiClient 对象 ApiClient client = getClient(); // 需要按需修改里面的返回字段、查询条件等 QueryParamRequest queryParamRequest = packRequestParam(); ApiResponse response = client.listSync(API_ID, queryParamRequest); System.out.println(getResultString(response)); } /** * 同步调用Create类型API */ public static void syncCreate() { // 获取 ApiClient 对象 ApiClient client = getClient(); // 按需修改入参信息 ManipulationParamRequest manipulationParamRequest = packDmlRequestParam(); ApiResponse response = client.createSync(API_ID, manipulationParamRequest); System.out.println(getResultString(response)); } /** * 同步调用Update类型API */ public static void syncUpdate() { // 获取 ApiClient 对象 ApiClient client = getClient(); // 按需修改入参信息 ManipulationParamRequest manipulationParamRequest = packDmlRequestParam(); ApiResponse response = client.updateSync(API_ID, manipulationParamRequest); System.out.println(getResultString(response)); } /** * 同步调用Delete类型API */ public static void syncDelete() { // 获取 ApiClient 对象 ApiClient client = getClient(); // 按需修改入参信息 ManipulationParamRequest manipulationParamRequest = packDmlRequestParam(); ApiResponse response = client.deleteSync(API_ID, manipulationParamRequest); System.out.println(getResultString(response)); } /** * 异步调用GET类型API * 需要在回调方法中处理响应结果 */ 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线程提前结束 ---"); } /** * 异步调用LIST类型API * 需要在回调方法中处理响应结果 */ 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线程提前结束 ---"); } /** * 获取 ApiClient 对象 */ public static ApiClient getClient() { ApiClientBuilderParams params = new ApiClientBuilderParams(); // 应用appKey params.setAppKey(APP_KEY); // 应用appSecret params.setAppSecret(APP_SECRET); // 访问域名或ip params.setHost(HOST); // 默认为http协议, 可根据API设置https协议 // 注意:Dataphin内置网关不支持https,阿里云网关支持https params.setScheme(Scheme.HTTP); // 访问API的数据环境,生产环境:RELEASE,开发环境:PRE params.setStage("RELEASE"); // 如果使用二级域名或未指定环境的独立域名,需要设置env // 有 PROD 和 PRE 两种值(如果是basic模式,传PROD; 如果是Dev-Prod模式,PROD表示查生产环境数据库,PRE表示查开发环境数据库) // 如果已经指定了访问环境的独立域名,则env参数不会起作用 params.setEnv("PROD"); ApiClient apiClient = new ApiClient(params); // 设置impala数据库类型的超时时间以及轮询间隔(可选,默认超时时间300s,轮询间隔800毫秒) // 参数只对impala有作用,调用非impala的API也要设置,保持默认即可 apiClient.setImpalaTimeoutAndInterval(300, 800); return apiClient; } public static SseApiClient getSseClient() { ApiClientBuilderParams params = new ApiClientBuilderParams(); // 应用appKey params.setAppKey(APP_KEY); // 应用appSecret params.setAppSecret(APP_SECRET); // 访问域名或ip params.setHost(HOST); // 默认为http协议, 可根据API设置https协议 // 注意:Dataphin内置网关不支持https,阿里云网关支持https params.setScheme(Scheme.HTTP); // 访问API的数据环境,生产环境:RELEASE,开发环境:PRE params.setStage("RELEASE"); // 如果使用二级域名或未指定环境的独立域名,需要设置env // 有 PROD 和 PRE 两种值(如果是basic模式,传PROD; 如果是Dev-Prod模式,PROD表示查生产环境数据库,PRE表示查开发环境数据库) // 如果已经指定了访问环境的独立域名,则env参数不会起作用 params.setEnv("PROD"); return new SseApiClient(params); } /** * 调用api包含consumer */ public static void fluxGet() { Consumer<ApiResponse> consumer = r -> System.out.println(new String(r.getBody())); SseApiClient sseApiClient = getSseClient(); // 对于短周期应用, 对于完成后可以将client的线程池关闭,释放资源 sseApiClient.getFlux(API_ID, packRequestParam()) // 对于临时运行,完成式需要关闭连接释放资源 .doOnComplete(sseApiClient::shutdown) .subscribe(consumer); } private static QueryParamRequest packRequestParamWithReturnNum() { QueryParamRequest queryParamRequest = packRequestParam(); queryParamRequest.setReturnTotalNum(true); return queryParamRequest; } /** * 包装请求对象 */ 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为请求字段名,1为id对应的值,可以设置多个查询参数 * 注意:如果是 IN 类型的参数,使用 List 包装参数值 */ Map<String, Object> conditions = new HashMap<>(); conditions.put("id", 1); conditions.put("age", Arrays.asList(10, 20, 30)); queryParamRequest.setConditions(conditions); /* * 返回参数列表,不能为空 * 例如指定返回id和name * 注意:返回参数如果不存在或没权限会报错 */ queryParamRequest.setReturnFields(Arrays.asList("id", "name")); /* * 排序字段,非必填 * 注意oracle和sqlServer使用分页需要同时使用排序 * 指定参数升序或者降序,可设置多个字段进行升序或者降序 * 例如返回结果按id进行升序 */ List<OrderBy> orderList = new ArrayList<>(); 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版本号,非必填,仅开发环境API支持设置 */ // queryParamRequest.setApiVersion("V1"); /********* API相关业务参数设置 end *********/ /********* 功能参数设置 begin *********/ /* * 是否使用模型缓存 * 开启会减少同一个服务单元API相同出入参时的解析频次,提高查询效率 */ queryParamRequest.setUseModelCache(false); /* * 是否使用结果缓存 * 开启则会缓存同一个API相同条件、相同返回字段的查询结果 * 适用于数据不变化的查询,减少相同SQL的查询频次,提高查询效率 * 缓存时长默认30分钟,3.5.6 版本后,在API开发页面可设置缓存时长 * 注意:如果API未开启结果缓存,该参数无效 */ queryParamRequest.setUseResultCache(false); /* * 是否保持字段的大小写格式 * 如果对大小写敏感,建议设置为true * 为false时,直连API返回结果的字段名默认为大写字母 */ queryParamRequest.setKeepColumnCase(true); /********* 功能参数设置 end *********/ return queryParamRequest; } /** * 包装DML请求对象 */ private static ManipulationParamRequest packDmlRequestParam() { ManipulationParamRequest manipulationParamRequest = new ManipulationParamRequest(); /* * 请求参数列表,非必填的参数可不传,必填参数必须传,否则会报错 * 其中key为对应的字段名,value为字段对应的值 * 例如这里的id为请求字段名,1为id对应的值,可以设置多个参数 * 注意:如果是 IN 类型的参数,使用 List 包装参数值 */ Map<String, Object> conditions = new HashMap<>(); conditions.put("id", 1); conditions.put("age", Arrays.asList(10, 20, 30)); manipulationParamRequest.setConditions(conditions); /* * 如果API的数据量是批量时,需要将入参放入batchConditions中 */ List<Map<String, Object>> batchConditions = new ArrayList<>(); batchConditions.add(conditions); manipulationParamRequest.setBatchConditions(batchConditions); /* * API版本号,非必填,仅开发环境API支持设置 */ // manipulationParamRequest.setApiVersion("V1"); return manipulationParamRequest; } /** * 获取结果字符串 */ private static String getResultString(ApiResponse response) { /* * step 1: 获取HttpResponse中头部的详细信息方式 * response.getHeaders().get(key) * 说明:key取值有"date\server\transfer-encoding\keep-alive\vary\connection\content-type\x-ca-request-id\x-ca-error-message\x-ca-error-code" * 如果API调用失败,Headers会有x-ca-error-message(错误信息描述)和x-ca-error-code(网关错误状态码),如果成功则不会存在该信息, * 但是x-ca-request-id(每次请求的唯一标识)始终会有。 * 推荐:如果返回code不是200,可打印出x-ca-error-message\x-ca-error-code以便排查问题 * 强制:使用中需要打印出x-ca-request-id,便于查看日志 * * step 2:下面已经打印出response的详细信息,实际开发中可以根据step1中描述,选择输出相关信息 */ System.out.println("返回结果详细信息: "+ SdkConstant.CLOUDAPI_LF + JSON.toJSONString(response) + SdkConstant.CLOUDAPI_LF); StringBuilder result = new StringBuilder(); result.append("Response from backend server").append(SdkConstant.CLOUDAPI_LF).append(SdkConstant.CLOUDAPI_LF); result.append("ResultCode:").append(SdkConstant.CLOUDAPI_LF).append(response.getCode()).append(SdkConstant.CLOUDAPI_LF).append(SdkConstant.CLOUDAPI_LF); result.append("RequestId:").append(SdkConstant.CLOUDAPI_LF).append(response.getHeaders().get("x-ca-request-id")).append(SdkConstant.CLOUDAPI_LF).append(SdkConstant.CLOUDAPI_LF); if (200 != response.getCode()) { result.append("ErrorCode:").append(SdkConstant.CLOUDAPI_LF).append(response.getHeaders().get("x-ca-error-code")).append(SdkConstant.CLOUDAPI_LF).append(SdkConstant.CLOUDAPI_LF); result.append("ErrorMessage:").append(SdkConstant.CLOUDAPI_LF).append(response.getHeaders().get("x-ca-error-message")).append(SdkConstant.CLOUDAPI_LF).append(SdkConstant.CLOUDAPI_LF); } result.append("ResultBody:").append(SdkConstant.CLOUDAPI_LF).append(new String(response.getBody(), SdkConstant.CLOUDAPI_ENCODING)); /* * 查看结果 如果状态码不是200,可查看x-ca-error-message报错信息排查问题 * 建议用户保存x-ca-request-id参数,如有异常请提供该参数以便我们排查问题 */ return result.toString(); } }
步骤三:初始化通信通道类
要调用API,首先要初始化客户端。您可以参考ClientDemo.java中getClient方法,使用对应的ApiClientBuilderParams类来进行初始化。其中,您需要将Host、APP_Key和APP_Secret三个变量进行替换。
步骤四:API接口说明
API接口类型
API接口类型分为查询类型(LIST、GET)和操作类型(CREATE、UPDATE、DELETE)。
LIST支持分页查询而GET不支持分页查询,请参考
ClientDemo.java中packRequestParam方法,设置QueryParamRequest里的参数。操作类型API请参考
ClientDemo.java中的packDmlRequestParam方法,设置ManipulationParamRequest里的参数。
调用API接口
SDK中的LIST和GET方法为Dataphin数据服务的通用方法,SDK中提供同步和异步的调用方法。在调用API之前,您需要根据您在Dataphin数据服务中定义的API填入相关的请求参数。
调试用例中
conditions为查询类API的业务请求参数,returnFields为API的返回参数,具体参数请参考服务 > 应用管理 > 已授权API服务页面,单击目标API操作列下调试,进入调试页面。操作类API的业务参数需要根据API配置的数据量进行区分,单条的入参通过
conditions进行传递,批量的入参需要通过batchConditions进行传递。请求参数中的API_ID,请参考服务 > 应用管理 > 已授权API服务页面API列下的API_ID。
Java SDK调用异步API流程
在调用API之前,您首先需要初始化客户端。
若API的响应时间较长,可使用异步调用,在整个等待应答期间,主线程不会被阻塞。
您可以实例化
QueryParamRequest对象,并且设置请求参数满足不同的查询需要,详情请参考调用实例中的packRequestParam方法。API请求和返回结果信息请查看SDK中的
APIDocument.md。若在使用中遇到问题,请咨询Dataphin技术支持。
步骤一:环境准备
Dataphin服务Java SDK适用于JDK 1.8及以上版本。
您需要准备一对授权密钥供SDK生成鉴权和签名信息,即AppKey和AppSecret。
AppKey和AppSecret可在服务 > 应用管理 > 我的应用列表中获取。
重要AppKey和AppSecret是Dataphin服务认证用户请求的密钥,这两个配置如果保存在客户端,请妥善加密。
在
pom.xml中添加如下依赖,如果添加dataphin-sdk-core-java报错请手动添加该JAR文件,路径JAVA_SDK/lib/dataphin-sdk-core-java-v5.4.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.4.0</version> </dependency>
步骤二:引入Java SDK的API接口调用类
在服务 > API市场 > API列表中下载对应的API文档。
导入
AsyncClientDemo.java,修正AsyncClientDemo.java类的import和package。package com.alibaba.dt.dataphin; 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 java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; /** * 异步API示例 * <p> * 使用方式: * 先配置好 HOST/APP_KEY/APP_SECRET/API_ID, * 再按需设置 getClient() 中的变量以及 packQueryParamRequest() 中的参数值 * 注意: * getClient() 中的参数可能会因不同的 api 而设置不同的值,可以将 getClient() 改造成带有入参,以适应不同 api 使用不同的参数。 */ public class AsyncClientDemo { /** * 访问域名或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(); try { AsyncQueryResults asyncQueryResults = asyncApiClient.listAsyncWaitFinish(API_ID, queryParamRequest); System.out.println(JSONObject.toJSONString(asyncQueryResults)); } catch (Throwable e) { e.printStackTrace(); } // 关闭客户端,回收资源 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(); } /** * 获取 AsyncApiClient 对象 */ public static AsyncApiClient getClient() { ApiClientBuilderParams params = new ApiClientBuilderParams(); // 应用appKey params.setAppKey(APP_KEY); // 应用appSecret params.setAppSecret(APP_SECRET); // 访问域名或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为请求字段名,1为id对应的值,可以设置多个查询参数 * 注意:如果是 IN 类型的参数,使用 List 包装参数值,例如这里的age */ HashMap<String, Object> conditions = new HashMap<>(); conditions.put("id", 1); conditions.put("age", Arrays.asList(10,20,30)); queryParamRequest.setConditions(conditions); /* * 返回参数列表,必填 * 例如指定返回id和name * 注意:返回参数如果不存在或没权限会报错 */ queryParamRequest.setReturnFields(Arrays.asList("id", "name")); /* * 排序字段,非必填 * 注意oracle和sqlServer使用分页需要同时使用排序 * 指定参数升序或者降序,可设置多个字段进行升序或者降序 * 例如返回结果按id进行升序 */ List<OrderBy> orderList = new ArrayList<>(); 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,首先要初始化客户端。您可以参考AsyncClientDemo.java中getClient方法,使用对应的ApiClientBuilderParams类来进行初始化。其中,您需要将Host、APP_Key和APP_Secret三个变量进行替换。
步骤四:API接口说明
API接口类型
API接口类型分为LIST和GET,LIST支持分页查询而GET不支持,请参考
AsyncClientDemo.java中的packRequestParam方法,设置QueryParamRequest里的参数。调用API接口
SDK中的LIST和GET方法为Dataphin数据服务的通用方法,SDK中同时提供同步和异步的调用方法。在调用API之前,您需要根据您在Dataphin数据服务定义的API填写相关的请求参数。
调试用例中
conditions为业务请求参数,returnFields为API的返回参数,具体参数请参考服务 > 应用管理 > 已授权API服务页面,单击目标API操作列下调试,进入调试页面。请求参数中的API_ID,请参考服务 > 应用管理 > 已授权API服务页面API列下的API_ID。
Python SDK调用流程
步骤一:环境准备
Python SDK适用于Python3.9及以上版本。
Python SDK获取方式如下:
在Dataphin首页的顶部菜单栏,选择服务 > 应用管理。
在左侧导航栏单击调用说明。
单击API调用示例页签,单击页面右上方的python调用示例下载按钮,获取Python SDK core包。
准备一对授权密钥供SDK生成鉴权和签名信息,即AppKey和AppSecret。
重要AppKey和AppSecret是Dataphin服务认证用户请求的密钥,这两个配置如果保存在客户端,请妥善加密。
准备一个JSON文件,格式如下:
{ "host": "API网关域名", "port": 80, "impalaConfig": { "pollingTimeout": 300, "pollingInterval": 800 }, "applicationConfig": { "appKey": "敏感数据自行填充", "appSecret": "敏感数据自行填充" }, "apiConfig": { "apiNo": 10008, "scheme": "HTTP", "stage": "RELEASE", "env": "PROD", "method": "LIST", // GET、LIST、CREATE、UPDATE、DELETE,区分大小写 "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,非必填,使用代理模式时需要配置此参数 }, "manipulationParamRequest": { "conditions": {"id": "1"}, // 数据量为“单条”的API的请求参数,非必填参数可不传,必填参数必须传 "batchConditions": [ // 数据量为“批量”的API的请求参数,非必填参数可不传,必填参数必须传 {"id": "1"}, {"id": "2"} ] } } }
步骤二:部署Python SDK
安装Python开发工具PyCharm。
打开Python项目。
在Demo类的启动参数上配置JSON文件路径。
具体调用请参照demo.py。
步骤三:调用API
在JSON文件中配置调用参数信息。
Python SDK通过读取JSON文件来组装API调用的基础参数。
调用
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', '')) # This is a JSON file for reading context. If you don't need a JSON file, just fill in the corresponding values directly # Gateway call address host = json_obj["host"] # Gateway call port port = json_obj["port"] # No configuration is required. Only valid for Impala type APIs, polling timeout pollingTimeout = json_obj["impalaConfig"]["pollingTimeout"] # No configuration is required. Only valid for Impala type APIs, polling interval pollingInterval = json_obj["impalaConfig"]["pollingInterval"] # Which app do you use to call this API for app information appKey = json_obj["applicationConfig"]["appKey"] appSecret = json_obj["applicationConfig"]["appSecret"] # Information about API apiId = json_obj["apiConfig"]["apiNo"] # How to call the API? The value is: HTTP or HTTPS. Note that the private gateway only supports HTTP [case sensitive] scheme = json_obj["apiConfig"]["scheme"] # Just write 'RELEASE' stage = json_obj["apiConfig"]["stage"] # There are two values: PROD and PRE (if in basic mode, PROD is passed to death; if in Dev Pro mode, PROD represents checking the production library, and PRE represents checking the development library [case sensitive]) env = json_obj["apiConfig"]["env"] # Query API Request parameters queryParam = json_obj["apiConfig"]["queryParamRequest"] # Manipulation API Request parameters manipulationParam = json_obj["apiConfig"]["manipulationParamRequest"] # Is the API GET/LIST/CREATE/UPDATE/DELETE? Distinguish between uppercase and lowercase letters method = json_obj["apiConfig"]["method"] if (host == None or host == ""): raise Exception("host is missing") if (appKey == None or appKey == ""): raise Exception("appKey is missing") if (appSecret == None or appSecret == ""): raise Exception("appSecret is missing") if (method == None or method == ""): raise Exception("method is missing") if (apiId == None or apiId == ""): raise Exception("apiNo is missing") # 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) # sync query API request resp = apiClient.callApi(queryParam) print(resp) # async query API request asyncResp = apiClient.asyncCallApi(queryParam) print(asyncResp) # flux API request sseClient = dataapi.SseApiClient(myConfig) fluxResp = sseClient.fluxCallApi(queryParam) for item in fluxResp: print(item) # sync manipulation API request resp = apiClient.callApi(manipulationParam) print(resp)
白名单调用方式(仅私有化部署时支持)
通过配置白名单免密方式访问API的安全策略,可简化API调用流程。IP白名单策略为应用级别策略,目前仅私有云支持此方式调用。
开发流程
步骤一:后台配置
您需要在数据服务中创建API、应用、应用白名单以及将应用和API进行绑定,才能通过白名单方式访问API。
创建API:您可在服务 > API开发 > API服务的API页面,选择对应的方式创建API,详情请参见创建API。
创建应用及应用白名单:应用可用于调用生产环境的API,并可为API设置白名单,如何创建应用及白名单,请参见新建及管理我的应用。
应用和API绑定:需申请该API的所属应用权限才能使用该API,如何申请,请参见管理API权限。
步骤二:发起请求
请求类型:POST
只支持POST提交的请求,BODY一律使用JSON字符串,并且Content-Type设置为
application/octet-stream; charset=utf-8。设置公共入参
参数名
位置
是否必填
示例
说明
accept
Header
是
application/json; charset=utf-8
响应格式。
host
Header
是
gateway.aliyun.com
API网关域名。
x-ca-key
Header
是
敏感数据自行填充
appkey,调用API的身份标识。
x-ca-stage
Header
是
RELEASE
环境标识。
RELEASE访问生产环境。
PRE访问开发环境。
Content-Type
Header
是
application/octet-stream; charset=utf-8
请求格式。
whitelist-flag
Header
是
1
白名单标识(非空),固定传1。
请求格式
URL:POST [host]/method/apiId?appKey=应用的AppKey&env=PROD
host:API网关域名(可在服务 > 服务管理 > 网络配置页面获取)。
method:API的操作类型,GET/LIST/CREATE/UPDATE/DELETE(可在服务 > 应用管理> 已授权API服务 > 调试页面获取)。
apiId:API的唯一标识(可在服务 > 应用管理> 已授权API服务 > 调试页面获取)。
appKey:该API绑定的应用的唯一标识(可在服务 > 应用管理 > 我的应用页面获取)
env:环境标识,PROD表示访问生产环境上的API,PRE表示访问开发环境的API。
请求URL示例:
gateway.aliyun.com/list/12345?appKey=xxx&env=PROD。
使用PostMan调用示例
步骤一:请求地址
请求POST地址
[host]/method/apiId?appKey=应用的AppKey&env=PROD。步骤二:填入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步骤三:填入body
说明Content-Type使用
application/octet-stream; charset=utf-8。body示例:
{ "conditions": {"id": "1"}, // 请求参数列表,根据参数决定,非必填参数可不传,必填参数必须传 "batchConditions": [{"id": "1"}], // 数据量为“批量”的操作类API的请求参数,非必填参数可不传,必填参数必须传 "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 | APP的Secret错误 | 检查传入的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 | Olap的Session错误。 |
DPN.Oltp.Olap.SessionNotFound | Olap的Session不存在。 |
常见问题
问题1:调用API报404 回答:
如果绑定了独立域名,请检查是HTTP协议还是HTTPS协议。
检查调用的API的操作类型是否和API的一致,因为操作类型会作为URL的一部分,确保根据操作类型调用正确的方法。
检查API是否发布到对应的环境。
问题2:调用API报400 回答:
请检查
x-ca-timestamp是否在15分钟的有效期内,x-ca-nonce在15分钟内是否被重复使用,建议每次请求API,x-ca-timestamp取当前时间,x-ca-nonce新生成可以用UUID生成,作为唯一标识,没有格式要求。检查使用AppKey、AppSecret是否前后有空格。
检查调用的API是否已授权,并且授权的APP的AppKey、Secret和参数APP_KEY、APP_SECRET是否一致。
注意检查客户端的签名值是否多加了空格,传给服务端的没有加(Invalid Signature),检查
stringToSign中的值是否有空格,如客户端签名Content-Type:application/octet-stream; charset=utf-8有空格,但是传给服务端的没有空格Content-Type:application/octet-stream;charset=utf-8,就会报错Invalid Signature。
问题3:调用API报403
回答:
检查API配置的调用协议是HTTP还是HTTPS,在代码中设置为对应的参数。
检查AppKey和AppSecret是否正确。
检查调用的API的操作类型是否和API的一致,因为操作类型会作为URL的一部分,确保根据操作类型调用正确的方法。
问题4:调用API报错:return fields missing in param
回答:在packRequestParam方法中,按下面方式设置参数:
List<String> returnFields = Lists.newArrayList("api的返回字段1","api的返回字段2",..."api的返回字段n");
queryParamRequest.setReturnFields(returnFields);问题5:如何使用operator为IN的参数
回答:在SDK调用时,IN类型的参数需要使用LIST传递参数值,例如:
假设参数名为p1,参数类型为String或Date,参数值为a、b、c,则应按下面方式设置参数:
Map<String, Object> conditions = Maps.newHashMap();
conditions.put("p1",Lists.newArrayList("a", "b", "c"));如果是数值类型,参数值为1、2、3,则应按下面方式设置参数:
Map<String, Object> conditions = Maps.newHashMap();
conditions.put("p1",Lists.newArrayList(1,2,3));问题6:使用SDK分页获取数据时,数据总数正确,但存在重复数据
原因:API代码中未使用排序字段使每次的排序结果唯一,或数据库本身不支持排序,导致每次分页获取数据时的查询结果的排序不一致,导致重复获取数据或丢失数据。
回答:确保返回结果排序的稳定性。若有主键,可增加主键字段排序,如果没有主键,使用多个字段组成联合主键排序,确保每次排序的结果是稳定的。
问题7:使用SDK分页获取数据时,如何设置参数返回总数
回答:在packRequestParam方法中,按下面方式设置参数:
// 是否返回总数(用于支持分页的api查询)
queryParamRequest.setReturnTotalNum(false);