数据服务

更新时间:
复制为 MD 格式

数据管理DMS提供的数据服务,能够将您在DMS中管理的数据以API的形式快速对外输出。本文为您介绍对API进行开发、测试、发布、上线、下线等操作。

前提条件

已将数据源录入DMS,且已开启安全托管(稳定变更和自由操作实例)或安全协同功能。更多信息,请参见云数据库录入他云/自建数据库录入开启安全托管变更管控模式

注意事项

  • 此功能正在邀测中,仅部分用户可以使用。

  • 修改后的API,需要进行重新发布才会生效。

  • 删除API时,会对API进行下线处理,即同步删除服务开发服务管理页签中的API。

  • 执行删除操作后,相关数据将无法恢复,请谨慎进行操作。

服务开发

服务开发页签,您可新建、编辑、测试API。API后发布,您可以将开发态的API发布至线上通过HTTPSSSE协议调用该API。

进入服务开发页签

  1. 登录数据管理DMS 5.0

  2. 在顶部菜单栏中,选择数据资产 > 数据服务

    说明

    若您使用的是极简模式的控制台,请单击控制台左上角的2023-01-28_15-57-17.png图标,选择全部功能 > 数据资产 > 数据服务

  3. 可选:单击服务开发页签。

新建目录

  1. 进入服务开发页签

  2. 单击目录右侧的image,并选择新建目录

  3. 在弹出的新建目录对话框,输入目录名称

    说明

    目录名称由汉字、英文字母、数字、下划线(_)组成,有如下要求:

    • 名称唯一。

    • 以英文字母或者汉字开头。

    • 长度为4~50个字符。

  4. 可选:输入业务描述

  5. 单击确认

新建并配置API

  1. 进入服务开发页签

  2. 可选新建目录

  3. 新建API。

    1. 在目标目录的右侧,单击image,并选择新建API

    2. 在弹出的新建API对话框,输入API名称

      说明

      API名称由汉字、英文字母、数字、下划线(_)组成,有如下要求:

      • 名称唯一。

      • 以英文字母或者汉字开头。

      • 长度为4~50个字符。

    3. 可选:输入业务描述

    4. 路径文本框,输入API的调用路径。

      说明

      该路径为API调用地址的组成部分,仅只支持英文、数字、下划线(_)、短划线(-),必须以/开头(例如/item/add)且唯一。

    5. 单击确认

  4. 配置API。

    1. 单击目标API名称。

    2. 配置API参数。

      配置项

      配置条件

      说明

      类别

      参数

      API模式

      选择模式

      必配

      支持向导模式脚本模式

      • 向导模式:通过可视化的方式选择表、字段,定义API的数据查询配置。

      • 脚本模式:通过手动编写SQL脚本和变量的方式,定义API的数据查询配置。

      选择表

      数据源类型

      必配

      待查询的数据库类型,当前仅支持MySQLPolarDB MySQL

      数据源名称

      待查询的数据库。

      说明

      可以通过输入关键字,快捷查询当前用户有查询权限的数据库。

      数据表名称

      向导模式

      待查询的数据表。

      说明

      可以通过输入关键字,快捷查询目标表。

      选择参数

      返回结果分页

      向导模式

      是否对返回结果分页。

      设置为请求参数

      是否将字段设置为请求参数。

      若您勾选字段前的设置为请求参数,该字段将会被添加到右侧的请求参数中。

      说明

      将字段设置为请求参数后,您可以在右侧单击请求参数,设置字段信息

      设置为返回参数

      是否将字段设置为返回参数。

      若您勾选字段前的设置为返回参数,该字段将会被添加到右侧的返回参数中。

      说明

      将字段设置为返回参数后,您可以在右侧单击返回参数,设置字段信息

      添加到字段排序

      单击字段后的添加,可以将该字段添加到排序字段区域,以进行排序。

      排序字段

      排序方式

      向导模式

      该字段的排序方式,支持升序降序

      操作

      可以单击上移下移,对字段进行排序;单击移除,取消对该字段的排序。

      编写查询SQL

      脚本模式

      输入SQL,然后单击自动解析参数,以生成请求参数和返回参数。

      说明

      请求参数和返回参数生成后,您可以在右侧单击请求参数返回参数,设置字段信息

    3. 可选:设置API的执行属性。

      单击页面右侧的属性,然后配置属性参数。

      参数

      说明

      协议

      调用API时使用的协议,支持HTTPSSSE

      最大返回记录数

      调用API时最多可返回的记录数量。

      超时时间

      调用API时的超时时间。

      返回字段元数据

      调用API是否返回元数据信息。

    4. 单击API信息上方的保存,保存API。

      screenshot_2025-09-09_14-29-52

测试API

  1. 进入服务开发页签

  2. 单击已新增并开发的API

  3. API信息上方,单击测试

  4. 在弹出的API测试页面,填入请求参数的

    image

  5. 单击开始测试

  6. API调用成功后,在返回内容区域查看是否符合预期。

    image

发布API

  1. 进入服务开发页签

  2. 单击已测试的API

  3. API信息上方,单击发布

  4. API发布申请面板中,确认API的基础信息和参数信息。

  5. 单击确定,等待API发布成功。

    说明

    若该API已经发布,则将覆盖线上API的配置。

    image

克隆API

  1. 进入服务开发页签

  2. 将鼠标指针放在目标API上,然后单击目标API后出现的image

  3. 单击克隆

    系统会自动克隆原API的相关信息,请确保参数符合要求

    说明
    • 克隆到克隆API对话框中的API名称路径会添加_copy后缀。

    • 须确保API名称在所有目录中具备唯一性。

  4. 可选:根据参数要求和实际情况,修改API名称业务描述路径目标文件夹

  5. 单击确认

修改API

  1. 进入服务开发页签

  2. 单击目标API名称。

  3. 修改API参数

    说明

    变更请求参数或返回参数可能影响API的调用。请根据变更信息,调整调用API请求参数和返回参数的处理逻辑。

  4. 单击API信息上方的保存,保存API。

    screenshot_2025-09-09_14-29-52

  5. 发布API

删除API

当您不再需要某个API时,可以执行如下操作删除该API。

说明

若该API已发布至线上,需先将其下线

  1. 进入服务开发页签

  2. 将鼠标指针放在目标API上,然后单击目标API后出现的image

  3. 单击删除

  4. 在弹出的删除对话框,单击确认删除

    image

编辑目录

  1. 进入服务开发页签

  2. 将鼠标指针放在目标目录上,然后单击目标目录后出现的image

  3. 单击编辑

  4. 在弹出的编辑目录对话框,修改目录信息。

  5. 单击确认

    image

删除目录

当您的需要某个目录中无上线的API,且无需保留该目录时,可以执行如下操作删除该目录。

  1. 进入服务开发页签

  2. 将鼠标指针放在目标目录上,然后单击目标目录后出现的image

  3. 单击删除

    说明

    请确保该目录中无上线的(服务状态服务中)API。

  4. 在弹出的删除对话框,单击确认删除

服务管理

服务管理页签展示了已发布至线上,或已下线且未删除的API。

进入服务开发页签

  1. 登录数据管理DMS 5.0

  2. 在顶部菜单栏中,选择数据资产 > 数据服务

    说明

    若您使用的是极简模式的控制台,请单击控制台左上角的2023-01-28_15-57-17.png图标,选择全部功能 > 数据资产 > 数据服务

  3. 单击服务管理页签。

API授权

  1. 进入服务开发页签

  2. 在当前页签的左侧导航栏,单击API管理

  3. API管理页面中,单击目标API操作列授权

    screenshot_2025-09-09_17-58-16

  4. 在弹出的授权对话框,选择授权账号并单击确认

    image

API下线

  1. 进入服务开发页签

  2. 在当前页签的左侧导航栏,单击API管理

  3. API管理页面中,单击目标API操作列下线

    说明

    API下线后,该API服务状态将变更为已停止

    image

API上线

  1. 进入服务开发页签

  2. 在当前页签的左侧导航栏,单击API管理

  3. API管理页面中,单击目标API操作列上线

    说明

    API上线成功后,该API服务状态将变更为服务中

    image

API测试

  1. 进入服务开发页签

  2. 在当前页签的左侧导航栏,单击API测试

  3. API测试区域,选择目标API

  4. 请求参数区域,填入请求参数的

  5. 单击开始测试

  6. API调用成功后,在返回内容区域查看是否符合预期。

    image

API调用

  1. 进入服务开发页签

  2. 在当前页签的左侧导航栏,单击API调用

  3. 查看API的调用信息,根据实际业务情况调用API。

API删除

说明

若该API已发布至线上,需先将其下线

  1. 进入服务开发页签

  2. 在当前页签的左侧导航栏,单击API管理

  3. API管理页面中,单击目标API操作列删除

  4. 在弹出的删除对话框,单击确认删除

    image

附录

支持的数据源

  • MySQL

    包含RDS MySQL、本地自建MySQL和他云MySQL数据库。

  • PolarDB MySQL

字段信息

说明

脚本模式生成的请求参数和返回参数,无示例值默认值描述

类型

参数

说明

请求参数

参数名称

调用API时的入参名称。

支持英文、数字、下划线(_)、短划线(-),且只能以英文或下划线(_)开头,1~50个字符,默认为字段名。

绑定字段

该字段的来源,即该字段对应的数据源中字段的名称。

参数类型

该字段的数据类型,支持STRING(字符串类型)、NUMBER(数字类型,包含整数,浮点数等)、BOOLEAN(布尔类型)、ARRAY(数组类型,元素可为字符串、数字和布尔类型)。

操作符

过滤条件的操作符,与参数名称和参数的取值共同过滤数据。

是否必填

该字段是否为必传参数。

示例值

该字段的取值示例。

默认值

该字段的默认取值。

描述

该字段的描述信息。

返回参数

别名

返回参数名称。

支持英文、数字、下划线(_)、短划线(-),且只能以英文或下划线(_)开头,1~50个字符,默认为字段名。

绑定字段

该字段的来源,即该字段对应的数据源中字段的名称。

参数类型

该字段的数据类型,支持STRING(字符串类型)、NUMBER(数字类型,包含整数,浮点数等)、BOOLEAN(布尔类型)、ARRAY(数组类型,元素可为字符串、数字和布尔类型)。

示例值

该字段的返回值示例。

默认值

该字段的默认返回值。

描述

该字段的描述信息。

支持的SQL

形式

说明

示例

普通SQL

使用#{}包裹请求参数名。

select c1, c2 from tb where c1 = #{c1};

select * from tb where id = #{id};

分页参数

支持两种格式:

  • 不需运算:使用#{}包裹分页参数。

  • 需运算(四则运算):使用${}包裹分页参数。

select * from tb where id = #{id} limit #{offset}, #{size};

select * from tb where id = #{id} limit ${pageNum} * ${pageSize}, ${pageSize};

if标签

在调用API时,只有当if语句中的条件满足时,该参数才会被添加至查询条件中。

select * from ds_test_tb where 1 =1
<if test="gmt_create != null">
and gmt_create = #{gmt_create}
</if>
<if test="id !=null">
and id = #{id}
</if>
limit ${pageNum} * ${pageSize}, ${pageSize}

choose标签

多个条件分支,任意一个条件满足时,该参数就会被添加至查询条件中。

select * from ds_test_tb where 1 =1
<choose>
 <when test="id != null">
 AND id = #{id}
 </when>
 <otherwise>
 AND `gmt_create` = #{gmt_create}
 </otherwise>
 </choose>
limit ${pageNum} * ${pageSize}, ${pageSize}

where标签

多个条件分支,所有条件都满足时,该参数才会被添加至查询条件中。

SELECT * FROM `ds_test_tb`
<where>
 <if test="id != null">
 id = #{id}
 </if>
 <if test="name != null">
 AND `name` = #{name}
 </if>
</where>

foreach标签

请求参数为列表类型。

重要

此时需手动调整请求参数中id_list的类型为ARRAY,然后保存。

SELECT * FROM `ds_test_tb` where id in
<foreach item="item" index="index" collection="id_list" open="(" separator="," close=")">
#{item}
</foreach>

调用示例

可通过 Java 代码对已部署的数据服务 API 发起调用,兼容HTTPSSSE两种通信协议,以下示例基于 Java 11 及以上版本,所需依赖如下

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.60</version>
</dependency>

请求结构

无论是通过 HTTPS 还是 SSE 协议调用,请求体的结构是相同的。

{
  "accessKey" : "xxx", #必填,DMS内凭证 AccessKey
  "accessSecret" : "xxx", #必填,DMS内凭证 AccessKey
  "query" : "call api ${apiPath}", # 必填,${apiPath}替换为api的路径
  "params" : { # 选填,根据参数实际数据类型填写
     "key1": value1,
     "key2": value2
  }
}

参数名

类型

是否必填

说明

accessKey

String

您在 DMS 内生成的凭证 AccessKey。

accessSecret

String

您在 DMS 内生成的凭证 AccessSecret。

query

String

固定格式为 call api ${apiPath},请将 ${apiPath} 替换为您的 API 实际路径。

params

Object

一个 JSON 对象,包含调用该 API 所需的所有请求参数及其值的键值对。若 API 无需参数,则此字段可省略。

重要

在 params 中,key都需要用双引号包裹,value应严格按实际数据类型书写,如字符串需用双引号包裹("abc"),数字、布尔值(true/false)均不加引号。

Https协议调用数据服务

适用于需要一次性获取完整结果集的标准查询场景。

import com.alibaba.fastjson.JSON;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class HttpsCallDataServiceApi {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) {
        try {
            String response = callDmsApi();
            System.out.println("响应内容: " + response);
        } catch (Exception e) {
            System.err.println("请求失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static String callDmsApi() throws Exception {
        // 替换为各region具体的服务地址,具体可见数据服务首页
        String url = "https://onequery-cn-hangzhou.proxy.dms.aliyuncs.com/service/http";

        Map<String, Object> requestBody = new HashMap<>();
        // 将 ${accessKey}、${accessSecret} 替换为用户的凭证信息,即DMS内部的凭证,而非RAM AK
        requestBody.put("accessKey", "${accessKey}");
        requestBody.put("accessSecret", "${accessSecret}");
        // 替换 ${apiPath} 为具体的api路径
        requestBody.put("query", "call api ${apiPath}");

        // 构建 params,若参数为空,则无需传递此参数
        Map<String, Object> params = new HashMap<>();
        // 在实际调用中,需将${param}替换为实际的参数
        // 数字类型参数
        params.put("userId", 111);
        // 字符串类型参数
        params.put("name", "abc");
        // 布尔类型参数
        params.put("isActive", true);
        // 列表类型参数
        params.put("tags", Arrays.asList(1, 2, 3));

        // 若参数为空,则无需put
        requestBody.put("params", params);

        String jsonBody = JSON.toJSONString(requestBody);

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/json;charset=utf-8")
                .method("POST", HttpRequest.BodyPublishers.ofString(jsonBody))
                .timeout(Duration.ofSeconds(30))
                .build();

        HttpResponse<String> response = httpClient.send(request,
                HttpResponse.BodyHandlers.ofString());

        // 检查响应状态码
        if (response.statusCode() != 200) {
            throw new RuntimeException("HTTP error code: " + response.statusCode());
        }

        return response.body();
    }
}

调用成功后,会返回一个包含完整结果集的 JSON 对象。

字段

类型

说明

type

String

结果类型。RESULTSET 代表成功的结果集,ERROR 代表执行错误。

traceId

String

本次查询的唯一 ID,可用于问题排查。

count

Number

结果集中的数据行数。

rows

Array

结果集数据。每个元素是一个代表数据行的 JSON 对象。

columnMetas

Array

字段元数据信息列表。

attributes

Object

查询相关的附加属性,如执行耗时 QueryTime

message

String

当 type 为 ERROR 时,此字段包含详细的错误信息。

{
  "attributes": {
    "QueryTime": 13
  },
  "columnMetas": [
    {
      "autoIncrement": true,
      "catalogName": "test_schema",
      "columnLabel": "id",
      "columnName": "id",
      "columnTypeName": "BIGINT UNSIGNED",
      "nullable": false,
      "precision": 20,
      "scale": 0,
      "schemaName": "",
      "tableName": "test_table"
    },
    {
      "autoIncrement": false,
      "catalogName": "test_schema",
      "columnLabel": "gmt_create",
      "columnName": "gmt_create",
      "columnTypeName": "DATETIME",
      "nullable": true,
      "precision": 19,
      "scale": 0,
      "schemaName": "",
      "tableName": "test_table"
    }
  ],
  "count": 1,
  "message": null,
  "rows": [
    {
      "id": 1,
      "gmt_create": "2025-12-17 16:23:53"
    }
  ],
  "sessionId": 1560935281,
  "traceId": "HZ1560935281OCQJOTKW",
  "type": "RESULTSET"
}

SSE协议调用数据服务

适用于长查询或需要逐步获取结果的场景。客户端将收到一个包含多个事件的消息流。

import com.alibaba.fastjson.JSON;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

public class SseCallDataServiceApi {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) {
        try {
            callDmsApiSse();
        } catch (Exception e) {
            System.err.println("SSE 请求失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void callDmsApiSse() throws Exception {
        // 替换为各region具体的服务地址,具体可见数据服务首页
        String url = "https://onequery-cn-hangzhou.proxy.dms.aliyuncs.com/service/sse";

        Map<String, Object> requestBody = new HashMap<>();
        // 将 ${accessKey}、${accessSecret} 替换为用户的凭证信息,即DMS内部的凭证,而非RAM AK
        requestBody.put("accessKey", "${accessKey}");
        requestBody.put("accessSecret", "${accessSecret}");
        // 替换 ${apiPath} 为具体的api路径
        requestBody.put("query", "call api ${apiPath}");

        // 构建 params,若参数为空,则无需传递该参数
        Map<String, Object> params = new HashMap<>();
        // 在实际调用中,需将${param}替换为实际的参数
        // 数字类型参数
        params.put("userId", 111);
        // 字符串类型参数
        params.put("name", "abc");
        // 布尔类型参数
        params.put("isActive", true);
        // 列表类型参数
        params.put("tags", Arrays.asList(1, 2, 3));
        // 若参数为空,则无需put
        requestBody.put("params", params);

        String jsonBody = JSON.toJSONString(requestBody);

        // 构建 HttpRequest,添加 SSE 必要的 Header
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type", "application/json;charset=utf-8")
                .header("Accept", "text/event-stream") // 指定接受 SSE 流
                .header("Cache-Control", "no-cache")
                .method("POST", HttpRequest.BodyPublishers.ofString(jsonBody))
                .timeout(Duration.ofMinutes(5)) // SSE 通常是长连接,超时时间设长一点
                .build();

        // 发送请求并使用 ofLines 处理流式响应
        System.out.println("开始接收 SSE 流...");

        httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofLines())
                .thenAccept(response -> {
                    if (response.statusCode() != 200) {
                        System.err.println("HTTP 错误: " + response.statusCode());
                        return;
                    }

                    // 逐行解析响应内容
                    try (Stream<String> lines = response.body()) {
                        lines.forEach(line -> {
                            if (line.startsWith("data:")) {
                                // 提取 data: 之后的内容
                                String data = line.substring(5).trim();
                                System.out.println("收到数据: " + data);
                            } else if (line.startsWith("error:")) {
                                System.err.println("收到错误: " + line);
                            }
                        });
                    }
                })
                .join(); // 为了演示效果,主线程等待异步执行完成
    }
}

SSE 响应是一个事件流,每个事件都以 data: 开头,其后跟随一个 JSON 对象。您需要关注该 JSON 对象中的 type 字段来判断事件类型。

type 值

事件类型

描述

META

元数据事件

流的第一个有效事件,包含结果集的字段元数据信息。

ROWS

数据行事件

包含一批(或一行)结果数据。一个查询可能会触发多次 ROWS 事件。

EOF

结束事件

End-Of-File,标志着所有数据已发送完毕。

ERROR

错误事件

查询过程中发生错误,此事件将包含详细的错误信息。

各类事件的 JSON 示例:

  • META 事件:

    {
      "attributes": {
        "QueryTime": 13
      },
      "columnMetas": [
        {
          "autoIncrement": true,
          "catalogName": "test_schema",
          "columnLabel": "id",
          "columnName": "id",
          "columnTypeName": "BIGINT UNSIGNED",
          "nullable": false,
          "precision": 20,
          "scale": 0,
          "schemaName": "",
          "tableName": "test_table"
        },
        {
          "autoIncrement": false,
          "catalogName": "test_schema",
          "columnLabel": "gmt_create",
          "columnName": "gmt_create",
          "columnTypeName": "DATETIME",
          "nullable": true,
          "precision": 19,
          "scale": 0,
          "schemaName": "",
          "tableName": "test_table"
        }
      ],
      "message": null,
      "resultIndex": 1,
      "sessionId": 1560946281,
      "traceId": "HZ1560946281OGMJSFEX",
      "type": "META"
    }
  • ROWS 事件:

    {
      "attributes": {},
      "count": 1,
      "message": null,
      "resultIndex": 1,
      "rows": [
        [
          1,
          "2025-12-17 16:23:53"
        ]
      ],
      "sessionId": 1560946281,
      "traceId": "HZ1560946281OGMJSFEX",
      "type": "ROWS"
    }
  • EOF 事件:

    {
      "attributes": {
        "TotalRowCount": 1
      },
      "lastResult": true,
      "message": null,
      "resultIndex": 1,
      "sessionId": 1560946281,
      "traceId": "HZ1560946281OGMJSFEX",
      "type": "EOF"
    }
  • ERROR 事件:

    {
      "attributes": {},
      "message": "[3050: Building Plan Error] PlanDAG build failed: The API does not exist. Publish it and try again.",
      "sessionId": 1560944281,
      "traceId": "HZ1560944281VWJLYLAK",
      "type": "ERROR"
    }