序曲
-
今天是五月初五端午节,尽享传统饮食:早上煮鸡蛋、面条荷包蛋、粽子;中午饺子。记录一下黑腿配白脚(饺)。
黑腿配白脚(饺)
- 另外,启用我的顶级域名
package com.erbadagang.*
。
言归正传,好记忆不如烂笔头,今天记录一下Dataway 数据接口配置服务
,作者赵永春,支持国货!
Dataway 数据接口配置服务
依托 DataQL 服务聚合能力,为应用提供一个 UI 界面。并以 jar 包的方式集成到应用中。 通过 Dataway 可以直接在界面上配置和发布接口。
一、简介
这种模式的革新使得开发一个接口不必在编写任何形式的代码,只需要配置一条 DataQL 查询即可完成满足前端对接口的需求。 从而避免了从数据库到前端之间一系列的开发配置任务,例如:Mapper、DO、DAO、Service、Controller 统统不在需要。
Dataway特意采用了 jar包集成的方式发布,这使得任意的老项目都可以无侵入的集成 Dataway。 直接改进老项目的迭代效率,大大减少企业项目研发成本。
基于 Spring Boot 项目使用 Dataway 来简单的配置接口。Dataway 的方式确实给人耳目一新,一个接口竟然可以如此简单的配置出来无需开发任何一行java代码,也不需要做任何 Mapping 实体映射绑定。
整个接口配置、测试、冒烟、发布。一站式都通过 Dataway 提供的 UI 界面完成。UI 会以 Jar 包方式提供并集成到应用中并和应用共享同一个 http 端口,应用无需单独为 Dataway 开辟新的管理端口。
这种内嵌集成方式模式的优点是,可以使得大部分老项目都可以在无侵入的情况下直接应用 Dataway。进而改进老项目的迭代效率,大大减少企业项目研发成本。
二、 工作机制

如上图所示 Dataway 在开发模式上提供了巨大的便捷。虽然工作流程中标识了由后端开发来配置 DataQL 接口,但这主要是出于考虑接口责任人。 但在实际工作中根据实际情况需要,配置接口的人员可以是产品研发生命周期中任意一名角色。
三、使用场景
主打场景并不是说 Dataway 适用范围仅限于此,而是经过多次项目实践。我们认为下面这些场景会有非常好的预期效果。 比如说 取数据 在一些报表、看板项目中即便是取数据逻辑在复杂。我们依然做到了真正的 零 开发,所有取数逻辑全部通过 DataQL + SQL 的方式满足。 对比往期项目对于后端技术人员的需求从 3~5 人的苦逼通宵加班,直接缩减为 1人配置化搞定。
再比如,某个内部类 ERP 项目,20多个表单页面,后端部分仅有 1000 行左右的核心代码。其它数据存取逻辑全部配置化完成。
3.1 取数据
- 在一些
报表、看板
纯展示类的项目中。我们做到了所有接口真正的零
开发全配置。所有取数逻辑全部通过 DataQL + SQL 的方式满足。 在此期间遇到最大的挑战是复杂查询中需要拼SQL
,随着 DataQL 查询组件的完善,这一问题被攻克。 - 对比往期项目对于后端技术人员的需求从 3~5 人的苦逼通宵加班,直接缩减为 1 人配置化搞定 。即便是第二天要上线新的逻辑,通过 DataQL + SQL。依然可以分分钟满足需求变更[吹牛进行中......]。
总结:如果你只想从数据库或者服务中获取某类数据,不需要: VO、BO、Convert、DO、Mapper 这类东西。
3.2 存数据
如果是从页面表单递交数据到数据库或者服务,免去 BO、FormBean、DO、Mapper 这类东西。如:某个 ERP 项目中,20多个表单页面。每个表单页面或多或少都有直接将单据数据录入到数据库的场景,每个单据的录入逻辑都有很大的不同。 其它数据存取逻辑全部配置化完成。
3.3 数据聚合
基于服务调用结果经过结构转换并响应给前端。将数据库和服务等多个结果进行汇聚然后返回给前端。和 GraphQL 相同,这是设计 DataQL 的初衷。将数据库和服务等多个结果进行汇聚然后返回给前端,这是 DataQL 的使命。 Dataway 是这一过程变得更加简单和高效。
四、 Spring Boot 整合
Dataway 是 Hasor 生态中的一员,使用 Dataway 第一步需要通过 hasor-spring 打通两个生态。
4.1 引入依赖
根据官方文档中推荐的方式我们将 Hasor 和 Spring Boot 整合起来。这里是原文:原文。
查看最新版本:https://mvnrepository.com/artifact/net.hasor/hasor-dataway
<!-- 引入hasor依赖 -->
<dependency>
<groupId>net.hasor</groupId>
<artifactId>hasor-spring</artifactId>
<version>4.1.8</version><!-- 查看最新版本:https://mvnrepository.com/artifact/net.hasor/hasor-spring -->
</dependency>
<dependency>
<groupId>net.hasor</groupId>
<artifactId>hasor-dataway</artifactId>
<version>4.1.8</version><!-- 查看最新版本:https://mvnrepository.com/artifact/net.hasor/hasor-dataway -->
</dependency>
hasor-spring 负责 Spring 和 Hasor 框架之间的整合。
hasor-dataway 是工作在 Hasor 之上,利用 hasor-spring 我们就可以使用 dataway了。
4.2 启用 Hasor
在SprintBoot 中启用 Hasor,这一步非常简单,只需要在 Spring 启动类上增加两个注解即可。
@EnableHasor() // 在Spring 中启用 Hasor
@EnableHasorWeb() // 将 hasor-web 配置到 Spring 环境中,Dataway 的 UI 是通过 hasor-web 提供服务。
4.3 启用 Dataway
然后第二步,在应用的application.properties
配置文件中启用 Dataway
# 启用 Dataway 功能(默认不启用)
HASOR_DATAQL_DATAWAY=true
# 开启 ui 管理功能(注意生产环境必须要设置为 false,否则会造成严重的生产安全事故)
HASOR_DATAQL_DATAWAY_ADMIN=true
# (可选)API工作路径
HASOR_DATAQL_DATAWAY_API_URL=/api/
# (可选)ui 的工作路径,只有开启 ui 管理功能后才有效
HASOR_DATAQL_DATAWAY_UI_URL=/interface-ui/
Dataway 一共涉及到 5个可以配置的配置项,但不是所有配置都是必须的。
其中 HASOR_DATAQL_DATAWAY、HASOR_DATAQL_DATAWAY_ADMIN 两个配置是必须要打开的,默认情况下 Datawaty 是不启用的。
4.4 初始化必要的表(例:MySQL)
CREATE TABLE `interface_info` (
`api_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`api_method` varchar(12) NOT NULL COMMENT 'HttpMethod:GET、PUT、POST',
`api_path` varchar(512) NOT NULL COMMENT '拦截路径',
`api_status` int(2) NOT NULL COMMENT '状态:0草稿,1发布,2有变更,3禁用',
`api_comment` varchar(255) NULL COMMENT '注释',
`api_type` varchar(24) NOT NULL COMMENT '脚本类型:SQL、DataQL',
`api_script` mediumtext NOT NULL COMMENT '查询脚本:xxxxxxx',
`api_schema` mediumtext NULL COMMENT '接口的请求/响应数据结构',
`api_sample` mediumtext NULL COMMENT '请求/响应/请求头样本数据',
`api_option` mediumtext NULL COMMENT '扩展配置信息',
`api_create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`api_gmt_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`api_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT='Dataway 中的API';
CREATE TABLE `interface_release` (
`pub_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Publish ID',
`pub_api_id` int(11) NOT NULL COMMENT '所属API ID',
`pub_method` varchar(12) NOT NULL COMMENT 'HttpMethod:GET、PUT、POST',
`pub_path` varchar(512) NOT NULL COMMENT '拦截路径',
`pub_status` int(2) NOT NULL COMMENT '状态:0有效,1无效(可能被下线)',
`pub_type` varchar(24) NOT NULL COMMENT '脚本类型:SQL、DataQL',
`pub_script` mediumtext NOT NULL COMMENT '查询脚本:xxxxxxx',
`pub_script_ori` mediumtext NOT NULL COMMENT '原始查询脚本,仅当类型为SQL时不同',
`pub_schema` mediumtext NULL COMMENT '接口的请求/响应数据结构',
`pub_sample` mediumtext NULL COMMENT '请求/响应/请求头样本数据',
`pub_option` mediumtext NULL COMMENT '扩展配置信息',
`pub_release_time`datetime DEFAULT CURRENT_TIMESTAMP COMMENT '发布时间(下线不更新)',
PRIMARY KEY (`pub_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT='Dataway API 发布历史。';
create index idx_interface_release on interface_release (pub_api_id);
4.5 初始化数据源
配置数据源
作为 Spring Boot 项目有着自己完善的数据库方面工具支持。我们这次采用 druid + mysql + spring-boot-starter-jdbc 的方式。
首先引入依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
然后增加数据源的配置
# db
spring.datasource.url=jdbc:mysql://xxxxxxx:3306/example
spring.datasource.username=xxxxx
spring.datasource.password=xxxxx
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type:com.alibaba.druid.pool.DruidDataSource
# druid
spring.datasource.druid.initial-size=3
spring.datasource.druid.min-idle=3
spring.datasource.druid.max-active=10
spring.datasource.druid.max-wait=60000
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=1
最后一步,将 Spring 使用的数据源导入到 Hasor 环境供 Dataway 使用。Spring Boot 和 Hasor 本是两个独立的容器框架,我们做整合之后为了使用 Dataway 的能力需要把 Spring 中的数据源设置到 Hasor 中。
首先新建一个 Hasor 的 模块,并且将其交给 Spring 管理。然后把数据源通过 Spring 注入进来。
package com.erbadagang.dataway.springmodule;
import net.hasor.core.ApiBinder;
import net.hasor.core.DimModule;
import net.hasor.db.JdbcModule;
import net.hasor.db.Level;
import net.hasor.spring.SpringModule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
@DimModule
@Component
public class ExampleModule implements SpringModule {
@Autowired
private DataSource dataSource = null;
@Override
public void loadModule(ApiBinder apiBinder) throws Throwable {
// .DataSource form Spring boot into Hasor
apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));
// .custom DataQL
//apiBinder.tryCast(QueryApiBinder.class).loadUdfSource(apiBinder.findClass(DimUdfSource.class));
//apiBinder.tryCast(QueryApiBinder.class).bindFragment("sql", SqlFragment.class);
}
}
4.6 启动工程
在启动日志中看到下列信息输出就表示 Dataway 已经可以正常访问了。
_ _ ____ _
| | | | | _ \ | |
| |__| | __ _ ___ ___ _ __ | |_) | ___ ___ | |_
| __ |/ _` / __|/ _ \| '__| | _ < / _ \ / _ \| __|
| | | | (_| \__ \ (_) | | | |_) | (_) | (_) | |_
|_| |_|\__,_|___/\___/|_| |____/ \___/ \___/ \__|
2020-06-25 10:59:37.476 INFO 13316 --- [ main] n.hasor.core.context.TemplateAppContext : loadModule class net.hasor.dataway.config.DatawayModule
2020-06-25 10:59:37.476 INFO 13316 --- [ main] net.hasor.dataway.config.DatawayModule : dataway api workAt /api/
2020-06-25 10:59:37.476 INFO 13316 --- [ main] n.h.c.environment.AbstractEnvironment : var -> HASOR_DATAQL_DATAWAY_API_URL = /api/.
2020-06-25 10:59:37.482 INFO 13316 --- [ main] net.hasor.dataway.config.DatawayModule : dataway self isolation ->net.hasor.dataway.config.DatawayModule
2020-06-25 10:59:37.483 INFO 13316 --- [ main] net.hasor.dataway.config.DatawayModule : dataway admin workAt /interface-ui/
-
dataway api workAt /api/
表示 API 的工作路径。 -
dataway admin workAt /interface-ui/
表示 管理配置界面的地址。
此时访问:http://<yourIP>:<yourProt>/interface-ui/
就可以看到配置页面了。
五、访问接口管理页面进行接口配置
在浏览器中输入 “http://127.0.0.1:8080/interface-ui/” 就可以看到期待已久的界面了。
5.1 接口状态流转

-
Editor:编辑状态,接口不可访问。
-
SmokeTest:冒烟测试是一个动作。只有冒烟测试通过之后才能进行发布操作,冒烟测试状态不会被持久保存。
-
Published:接口已发布可以正常访问,并且无增量变化。
-
Changes:接口已经发布可以正常访问,但是有后续变更尚未发布。此时访问接口是上一次发布的查询逻辑。
-
Disable:无效接口,说明接口曾经发布成功过。此时将接口进行下线处理。在编辑器页面可以修改重新发布。
-
Delete:接口已删除,被删除的接口会被真正的物理删除。interface_release 表中会保留历史数据。
5.2 新增接口
点击页面顶部的 New 就可以进入新增接口页面。

5.2 表内数据
表数据内容
5.3 执行
在任意的编辑器界面中(新增模式 or 编辑模式),都可以直接在编辑区编写 SQL 查询并通过右上角的 Execute
按钮执行。

-
另外一个稍为复杂进行关联查询的例子:
关联查询
sql语句:
-- 关联查询,根据商品id和订单用户查询关联信息。
select * from product p,orders o
where p.id= #{productID} and
o.product_id=#{productID} and
o.user_id=#{userId};
传入参数:
{
"productID": "1",
"userId": "1",
"payAmount": "10"
}
返回结果:
{
"success": true,
"message": "OK",
"code": 0,
"lifeCycleTime": 133,
"executionTime": 130,
"value": [
{
"id": 1,
"stock": 8,
"last_update_time": 1592512852000,
"user_id": 1,
"product_id": 1,
"pay_amount": 2,
"add_time": 1592512852000
},
{
"id": 4,
"stock": 8,
"last_update_time": 1592599603000,
"user_id": 1,
"product_id": 1,
"pay_amount": 1,
"add_time": 1592599603000
}
]
}
5.4 冒烟测试
点击保存按钮后可点击冒烟测试按钮进行冒烟测试。是否已经冒烟测试的状态未持久化,本地点击后按钮置灰,下一次再进入还可以点击。只有冒烟测试通过后才能进行下面的发布操作。
5.5 发布
当接口开发配置完成,需要将其发布以供使用。一个接口的发布上线要经历三个过程,具体如下:
- Execute,调试当前编辑器中的 DataQL 查询。
- Smoke Test,冒烟测试。和 Execute 不同,Smoke 同样是执行 DataQL 查询并要求查询正常执行完毕。 但是区别 Execute 的是: Smoke 不会使用本地编辑器中的语句,而是到数据库中获取对应的查询语句。 因为接口的发布也是将数据库中的查询语句进行发布。
-
Publish,当冒烟测试通过之后就可以点击发布按钮把接口发布上线了。每次发布 Dataway 都会在 interface_release 表中新增一条记录。
发布后数据库有记录
Postman进行接口测试:
Postman调用已发布接口
5.6 删除/下线
已经发布上线的接口只能执行接口下线操作。
已经下线的接口或者正在编辑中的接口可以执行删除操作,删除操作会物理删除 interface_info 表中对应的记录。 但是删除操作并不会删除曾经的发布历史,这就留给我们了一条可以找回被删除的接口曾经发布过的历史记录。只不过这一步只能进入数据库中自行搜索。

5.7 发布历史
每个 Dataway 上的接口在发布时都会 在interface_release
表中生成一条记录。发布历史看的就是这里的记录。

在历史记录列表的右侧 icon,点击可以恢复历史记录的内容到编辑器中。
六、本文源码
本文设计源代码可以从我的Gitee仓库dataway目录下载。
相关代码也可以从下面获得。
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.erbadagang.dataway</groupId>
<artifactId>dataway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dataway</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
</properties>
<dependencies>
<!-- 引入hasor依赖 -->
<dependency>
<groupId>net.hasor</groupId>
<artifactId>hasor-spring</artifactId>
<version>4.1.8</version><!-- 查看最新版本:https://mvnrepository.com/artifact/net.hasor/hasor-spring -->
</dependency>
<dependency>
<groupId>net.hasor</groupId>
<artifactId>hasor-dataway</artifactId>
<version>4.1.8</version><!-- 查看最新版本:https://mvnrepository.com/artifact/net.hasor/hasor-dataway -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.19</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.application.name=dataway
management.endpoints.jmx.exposure.include=*
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
# spring cloud access&secret config
# 可以访问如下地址查看: https://usercenter.console.aliyun.com/#/manage/ak
alibaba.cloud.access-key=****
alibaba.cloud.secret-key=****
# 应用服务 WEB 访问端口
server.port=8080
# Actuator Web 访问端口
management.server.port=8081
# 启用 Dataway 功能(默认不启用)
HASOR_DATAQL_DATAWAY=true
# 开启 ui 管理功能(注意生产环境必须要设置为 false,否则会造成严重的生产安全事故)
HASOR_DATAQL_DATAWAY_ADMIN=true
# (可选)API工作路径
HASOR_DATAQL_DATAWAY_API_URL=/api/
# (可选)ui 的工作路径,只有开启 ui 管理功能后才有效
HASOR_DATAQL_DATAWAY_UI_URL=/interface-ui/
# db
spring.datasource.url=jdbc:mysql://101.133.227.13:3306/seata_order?useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=IA8oDDk90e6V
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type:com.alibaba.druid.pool.DruidDataSource
# druid
spring.datasource.druid.initial-size=3
spring.datasource.druid.min-idle=3
spring.datasource.druid.max-active=10
spring.datasource.druid.max-wait=60000
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
spring.datasource.druid.filter.stat.log-slow-sql=true
spring.datasource.druid.filter.stat.slow-sql-millis=1
DatawayApplication
package com.erbadagang.dataway;
import net.hasor.spring.boot.EnableHasor;
import net.hasor.spring.boot.EnableHasorWeb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @description Dataway集成在Springboot项目中,通过UI方式配置接口。
* @ClassName: DatawayApplication
* @author: 郭秀志 jbcode@126.com
* @date: 2020/6/25 16:39
* @Copyright:
*/
@SpringBootApplication
@EnableHasor() // 在Spring 中启用 Hasor
@EnableHasorWeb() // 将 hasor-web 配置到 Spring 环境中,Dataway 的 UI 是通过 hasor-web 提供服务。
public class DatawayApplication {
public static void main(String[] args) {
SpringApplication.run(DatawayApplication.class, args);
}
}
网友评论