HTTP 接口只给一页、参数写死天天改?DataY 自动分页 + 动态参数
自动分页把每一页都拉全,动态参数每次执行都自动更新,配合自动建表,一个 ETL 任务全搞定。
01 一个很常见的场景
业务系统提供了查询接口,数据在接口里,报表却还在 Excel 里。
一开始大家想得很简单:写个脚本,定时请求一下,把结果写进数据库不就行了?
真正动手之后才发现,问题一个接一个:
- 接口一页只返回 10 条,只调一次永远拿不全;
- 查询条件里要传时间范围,脚本里的时间写死了,第二天就查不到新数据;
- 请求头里带着 token,换环境、换账号就要改;
- 返回的 JSON 层层嵌套,真正要写入表的数据藏在 std_data.result.rows 里;
- 目标表还没有,字段类型、建表语句都要自己处理;
- 最怕的是:脚本跑完了,你以为同步成功了,其实只同步了第一页。
这类“接口到数据库”的同步,本质上是 ETL 里非常典型的一类场景:HTTP 作为数据源,数据库作为目标端。
如果每个接口都手写一套脚本,维护成本会越来越高。更合理的方式,是把接口调用、分页循环、时间参数、字段解析、写库这些动作,变成可配置、可复用、可调度的 ETL 任务。
这篇文章就以一个真实的外包交付查询接口为例,看看 DataY 是怎么把这件事做完整的。
02 为什么 HTTP 接口同步“看起来简单,做起来坑”
数据库同步通常有现成的连接器,表结构、增量字段、分页都能交给工具处理。HTTP 接口则不一样,它更像“半结构化数据源”:
接口协议不统一 有的用 GET,有的用 POST;有的参数在 URL 上,有的在 JSON Body 里;鉴权可能在 Header,也可能在 Cookie。
返回结构不统一 数据可能直接是一个数组,也可能藏在 data.list、result.rows、std_data.result.rows 里。
分页方式不统一 有的用 page_no/page_size,有的用 offset/limit,有的用 cursor。
时间条件必须动态 今天的任务应该取“昨天”的数据,而不是脚本里写死的某一天。
写完还要能调度、能重试、能看日志 脚本能跑通只是第一步,稳定运行才是长期问题。
所以,一个真正可用的 HTTP 同步任务,至少要把下面几件事做好:
- 请求可配置:URL、方法、Header、Body;
- 参数可动态替换:页码、每页条数、时间范围;
- 分页可循环:一页一页拉,直到取完;
- 响应可解析:从嵌套 JSON 中提取数据数组;
- 目标可写入:自动建表、批量写入、支持追加/覆盖/更新;
- 过程可观测:有日志、有执行实例、有失败重试。
03 DataY 的解法:两个组件就够了
在 DataY 里,一个最简的“HTTP 同步到 MySQL”任务,只需要两个节点:
HttpInvoke ──▶ StreamJdbcOutput
调用接口 写入 MySQL
- HttpInvoke:负责发请求、解析响应、支持分页循环;
- StreamJdbcOutput:负责把数据写入关系型数据库,支持自动建表和多种写入策略。
任务设计器里拖两个组件、连一条线,再把接口参数填进去,一个可调度的 ETL 任务就成型了。
下面用实际配置一步步拆开。
04 第一步:把 cURL 变成 ETL 配置
业务方给的原始命令大概是这样:
curl –location –request POST 'https://your-api-gateway.example.com' \\
–header 'digi-service: {"name":"yz.oapi.outsourcing.delivery.query"}' \\
–header 'digi-user-token: <YOUR_TOKEN>' \\
–header 'Content-Type: application/json' \\
–data '{
"std_data": {
"parameter": {
"page_no": 1,
"use_has_next": true,
"page_size": 10
}
}
}'
在 DataY 的 HttpInvoke 配置里,可以直接“从 cURL 导入”,也可以手动填写:
- 请求 URL:https://your-api-gateway.example.com
- 请求方法:POST
- 请求头:Content-Type、digi-service、digi-user-token
- 请求体:接口要求的 JSON
- 数据路径:$.std_data.result.rows
这里的 数据路径 很关键。接口返回的 JSON 通常不是直接一个数组,而是类似:
{
"std_data": {
"parameter": { "page_no": 1, "page_size": 10 },
"result": {
"rows": [
{ "id": 1, "docNo": "DOC-0001", "entry_time": "2026-10-18 12:00:00" }
]
}
}
}
真正要写库的是 rows,所以数据路径填 $.std_data.result.rows。DataY 会把它提取成数组,并根据字段自动推断表结构。
05 分页:让 ${pageNo} 自己往前走
只调一次接口,最多只能拿到第一页。要拿全量数据,必须开启分页循环。
在 HttpInvoke 的分页配置里,只需要几项:
- 起始页码:1
- 每页条数:10
- 最大页数:1000(防止接口忽略分页参数导致死循环)
- 请求间隔:100ms(对接口友好一点)
请求体里用占位符表示页码和每页条数:
{
"std_data": {
"parameter": {
"page_no": ${pageNo},
"use_has_next": true,
"page_size": ${pageSize}
}
}
}
注意:${pageNo} 和 ${pageSize} 在 JSON 里是数字占位,不是字符串。DataY 在每次请求前会把它们替换成当前页码和每页条数。
分页什么时候停?
DataY 的判断很直接:当前页返回的条数小于 pageSize,说明已经是最后一页;如果返回空数组,也直接停止。
例如 pageSize = 10:
- 第 1 页返回 10 条 → 继续;
- 第 2 页返回 10 条 → 继续;
- 第 3 页返回 5 条 → 小于 10,停止;
- 如果总数刚好是 20 条,则第 3 页会返回空数组,同样停止。
这里有一个小细节:当总数刚好是 pageSize 的整数倍时,会多请求一次空页来确认结束。这是正常的,也是这种判断方式最简单、最稳妥的地方。
每一页数据都会作为独立的 FlowFile 向下游发送,边拉取边写入,不会把全量数据一次性堆在内存里。数据量大时,这一点非常重要。
06 时间参数化:一次求值,全页复用
接口查询通常都要带时间范围。最忌讳的写法是把日期写死:
"value": "2026-10-18 00:00:00"
第二天任务再跑,还在查昨天之前的旧数据。
DataY 支持在请求体里直接写动态时间表达式,例如:
{
"field_name": "entry_time",
"operator": ">=",
"value": "#{NOW – 1d, yyyy-MM-dd} 00:00:00"
}
{
"field_name": "entry_time",
"operator": "<=",
"value": "#{NOW – 1d, yyyy-MM-dd} 23:59:59"
}
#{NOW – 1d, yyyy-MM-dd} 会在任务执行时计算成“昨天”的日期。今天跑,取昨天;明天跑,自动变成新的昨天,不需要改配置。
除了“昨天”,还可以按需组合:
- 今天:#{NOW, yyyy-MM-dd} 00:00:00
- 最近 24 小时:#{NOW – 1d, yyyy-MM-dd HH:mm:ss} 到 #{NOW, yyyy-MM-dd HH:mm:ss}
- 最近 7 天:#{NOW – 7d, yyyy-MM-dd} 00:00:00
- 本月第一天:#{THIS_MONTH_FIRST_DAY}
更重要的是:分页任务开始时,时间表达式只会求值一次,后续所有页复用同一个时间范围。
为什么这一点很重要?
假设任务从 23:59:58 开始跑,第 1 页还在取“昨天”,翻到第 2 页时刚好跨过零点。如果每页都重新计算时间,后面的页可能就跑到“今天”去了,数据范围前后不一致,排查起来非常痛苦。
一次求值、全页复用,才能保证整个分页过程查的是同一个时间窗口。
07 写入 MySQL:自动建表,按需选择写入策略
HttpInvoke 提取出 rows 后,下游的 StreamJdbcOutput 负责写库。
配置项也很直接:
- 数据源:选择目标 MySQL;
- 表名:例如 yz_outsourcing_delivery;
- 写入策略:append、overwrite 或 update;
- 批处理数:例如 20000。
如果目标表不存在,DataY 会根据接口返回的数据自动推断字段和类型,并生成建表语句。第一次跑任务时自动建表,后续页继续追加,整个过程不需要手工写 DDL。
对于增量同步,建议配合业务主键使用 update 策略,或者在入库后做去重,避免任务重试时产生重复数据。
08 写在最后
HTTP 接口同步看起来只是“调个接口、写个库”,但要做到稳定、完整、可维护,背后其实是一整套 ETL 能力:
- 请求配置;
- 分页循环;
- 动态参数;
- JSON 解析;
- 自动建表;
- 批量写入;
- 调度与日志。
DataY 把这些能力收进了一个轻量平台里。一个 JAR 启动,拖两个组件,配好参数,就能把接口数据稳定地同步到 MySQL。
更重要的是,任务不是“一次性脚本”,而是可以被调度、被复用、被导出的标准 ETL 任务。今天对接外包交付查询,明天对接订单、库存、财务接口,只需要换 URL、Header 和 Body,剩下的分页、时间参数、写库逻辑都可以复用。
如果你也正在被“接口有数据、平台进不来”困扰,不妨从一个最简单的 HTTP 到 MySQL 任务开始。
先把第一页拿全,再把每一页拿稳。
09 DataY 是什么
上面这套链路,跑在 DataY 上。它是一个开源、轻量的一体化数据平台,目标很直接:用尽量小的资源,把数据集成、任务调度、数仓和指标分析这几件事跑通。
这里的“轻量”指的是运行资源门槛低:用尽量少的机器、内存和人力投入,就能完成数据平台建设——而不是能力轻量。数据平台该有的功能它都有:数据集成、维度建模、任务调度、高性能数仓、智能问数,一样不缺。
它不依赖 Hadoop、Spark 这类重型组件,一个 JAR 就能启动,默认内嵌 DuckDB 作为高性能分析引擎。开发机 2 核 4G 就能跑通从数据接入到报表查询的完整链路,部署和维护成本都比较低。
它由两块组成:
| DataY Core | 数据集成引擎 | 轻量、可嵌入、可扩展、流批一体;JSON 定义任务、自动建表、CDC 实时同步;可脱离 Web 独立运行或嵌入 Java 应用 |
| DataY Web | 可视化数据平台 | 拖拽式任务设计、任务调度、维度建模、指标管理、智能问数 |
目前 DataY 覆盖五块核心能力:数据集成、维度建模、任务调度、高性能数仓和智能问数。数据集成方面,支持 MySQL、PostgreSQL、Oracle、SQL Server、Doris、ClickHouse、DuckDB、DuckLake 等十余种数据源,也支持 MySQL CDC、PostgreSQL CDC、Oracle CDC 等实时同步场景。任务既可以在可视化画布上拖拽编排,也可以用 JSON 配置文件定义。
HTTP 接口同步就是其中一个很典型的场景:把接口调用、分页循环、参数替换、JSON 解析、字段映射和写库这些动作,收敛成一个可配置、可调度、可复用的 ETL 任务,而不是散落在各个脚本里。
快速开始:
git clone https://gitee.com/yuyuejia/datay.git
cd datay
mvn clean package -DskipTests
java -jar datay-web/target/*.jar –DATAY_AI_API_KEY=sk-xxxxxxxxx
# 浏览器打开 http://localhost:8080,默认账号 admin/admin
产品首页:http://datay.yuyuejia.com.cn/
项目地址:https://github.com/yuyuejia/datay
网硕互联帮助中心







评论前必须登录!
注册