SpringBoot 集成 Dataway 接口配置工具


编程515 阅0 评

这篇文章将在 SpringBoot 项目中集成 Dataway,并使用 Dataway 提供的 UI 页面在线创建一个分页查询的API接口。

概述

Dataway 是基于 DataQL(Data Query Language)服务聚合能力,为应用提供的一个接口配置工具。使得使用者无需开发任何代码就配置一个满足需求的接口。 整个接口配置、测试、冒烟、发布,一站式都通过 Dataway 提供的 UI 界面完成。这种内嵌集成方式模式的优点是,可以使得大部分老项目都可以在无侵入的情况下直接应用 Dataway。进而改进老项目的迭代效率,大大减少企业项目研发成本。

通过 Dataway 接口配置界面,使用自己的 DataQL 查询语言,可视化的接口配置,避免了从数据存取到前端接口之间的一系列开发任务(例如:Mapper、BO、VO、DO、DAO、Service、Controller),提高后端接口的开发效率。

CC2_A633_6D5C_MK4L

适用场景

取数据

  • 在一些 报表、看板 纯展示类的项目中。我们做到了所有接口真正的 零 开发全配置。所有取数逻辑全部通过 DataQL + SQL 的方式满足。 在此期间遇到最大的挑战是复杂查询中需要 拼SQL,随着 DataQL 查询组件的完善,这一问题被攻克。
  • 对比往期项目对于后端技术人员的需求从 3~5 人的苦逼通宵加班,直接缩减为 1 人配置化搞定 。即便是第二天要上线新的逻辑,通过 DataQL + SQL。依然可以分分钟满足需求变更。

存数据

  • 在内部某个类 ERP 项目中,20多个表单页面。每个表单页面或多或少都有直接将单据数据录入到数据库的场景,每个单据的录入逻辑都有很大的不同。 我们通过 DataQL + SQL 的方式在早期用了1000 行左右的核心代码。其它数据存取逻辑全部配置化完成。
  • 如今随着 DataQL 工具链的完善,其中绝大部分场景可以完全配置化无需开发了。

数据聚合

  • 和 GraphQL 相同,这是设计 DataQL 的初衷。将数据库和服务等多个结果进行汇聚然后返回给前端,这是 DataQL 的使命。 Dataway 是这一过程变得更加简单和高效。

集成

Dataway 是 Hasor 生态中的一员,因此在 Spring 中使用 Dataway 首先要关联两个生态。

1. 添加依赖

在POM文件中增加依赖:

<!-- Dataway -->
<dependency>
        <groupId>net.hasor</groupId>
        <artifactId>hasor-spring</artifactId>
        <version>4.1.7</version>
</dependency>
<dependency>
        <groupId>net.hasor</groupId>
        <artifactId>hasor-dataway</artifactId>
        <version>4.1.7</version>
</dependency>

2. 导入数据表

导入Dataway必须的配置表到数据库中,在 net.hasor:hasor-dataway jar包中可以找到sql文件,对应路径:

hasor-dataway-4.1.7.jar > META-INF > hasor-framework > mysql
  • interface_info.sql - Dataway 中的API配置表
  • interface_release.sql - Dataway API 发布历史记录表

3. 配置 Dataway

3.1 配置数据源

添加 DatawayConfig.java 配置类:

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 DatawayConfig implements SpringModule {
        // 注入现有数据源
        @Autowired
        private DataSource dataSource;
        
    @Override
        public void loadModule(ApiBinder apiBinder) throws Throwable {
                // 设置数据源
                apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));
        }
}

3.2 配置参数

在 application.yml 中进行配置:

# Dataway配置
启用 Dataway 功能(默认不启用)
HASOR_DATAQL_DATAWAY: true
# 开启 ui 管理功能(注意生产环境必须要设置为 false,否则会造成严重的生产安全事故)
HASOR_DATAQL_DATAWAY_ADMIN: true
# Api工作路径,注意不要与已有的接口地址冲突
HASOR_DATAQL_DATAWAY_API_URL: /dataway/api/
# Api可视化ui的工作路径,只有开启 ui 管理功能后才有效
HASOR_DATAQL_DATAWAY_UI_URL: /interface-ui/
# SQL执行器方言设置(可选,建议设置)
HASOR_DATAQL_FX_PAGE_DIALECT: mysql

3.3 启动 Dataway

@EnableHasor() // 在Spring 中启用 Hasor
@EnableHasorWeb() // 将 hasor-web 配置到 Spring 环境中,Dataway 的 UI 是通过hasor-web 提供服务

4. 自定义返回结构

Dataway 默认接口结构:

{
        "success": true,
        "message": "OK",
        "code": 0,
        "lifeCycleTime": 22,
        "executionTime": 21,
        "value": ...
}

这可能不适用我们当前接口返回的参数结构,可以使用 Dataway 提供的ResultProcess 拦截器自定义返回数据的结构:

{
        "success": true,
        "errorCode": "string",
        "errorDesc": "string",
        "data": ...
}

4.1 创建处理器

创建 UnifyResultPayloadChainSpi 类:

import net.hasor.dataway.spi.ApiInfo;
import net.hasor.dataway.spi.ResultProcessChainSpi;
import java.util.HashMap;
 
/**
 * Dataway接口统一返回结构
 */
public class UnifyResultPayloadChainSpi implements ResultProcessChainSpi {
        public Object callAfter(boolean formPre, ApiInfo apiInfo, Object result) {
                if (formPre) {
                        return result; // 如果前置拦截器处理了。那么后置拦截器就不处理。
                }
 
                  return new HashMap<String, Object>() {{
                          put("success", true);
                          put("data", result);
                  }};
        }
        
        public Object callError(boolean formPre, ApiInfo apiInfo, Throwable e) { 
                return new HashMap<String, Object>() {{
                        put("success", false);
                        put("errorDesc", e.getMessage());
                }};
        }
}

4.2 注册处理器

在 DatawayConfig 类里面,将上面创建的处理器注册到 Dataway 中:

@Override
public void loadModule(ApiBinder apiBinder) throws Throwable {
        // ... 其他代码
        // 注册拦截器:自定义接口统一响应结构体
        apiBinder.bindSpiListener(ResultProcessChainSpi.class, new
UnifyResultPayloadChainSpi());
}

5. 运行项目

访问接口配置页面:http://localhost:8080/tyrion/interface-ui

地址中的 /interface-ui 对应在 application.yml 文件中的HASOR_DATAQL_DATAWAY_UI_URL配置项

6. 创建接口

Dataway 工具化的提供 DataQL 配置能力,所以下面的接口查询代码会使用DataQL的语法结构,这里不对DataQL作阐述,详见:https://www.hasor.net/web/dataway/about.html

下面以创建一个分页查询的接口为例子:

①. 进入接口配置页面

dataway界面

②. 写入代码语句

dataway_add.png

  • 接口地址
GET /dataway/api/v1/news/list
  • 请求参数
{
        "pageNo": 0,
        "pageSize": 5,
        "title": ""
}
  • 查询代码
// SQL 执行器切换为分页模式[hint语句必须放在最前面] 
hint FRAGMENT_SQL_QUERY_BY_PAGE = true

// sql查询
var querySQL = @@sql(title)<%
        SELECT * FROM news_info WHERE title LIKE CONCAT('%', #{title}, '%') ORDER BY weight DESC
%>
 
// 创建分页查询对象
var pageQuery =    querySQL(${title})

// 设置分页信息
run pageQuery.setPageInfo({ 
        "pageSize" : ${pageSize}, // 页大小
        "currentPage" : ${pageNo} // 页码,从0开始
})
 
// 取出分页信息
var pageInfo = pageQuery.pageInfo()
// 查询出的数据,抽取只需要的字段返回给接口调用者 
var data = pageQuery.data() => [{
        'id', 'title',
        'link',
        'weight',
        'category'
}]
 
// 组装返回数据
return {
        "pageNo": pageInfo.currentPage,
        "pageSize": pageInfo.pageSize,
        "total": pageInfo.totalCount,
        "pages": pageInfo.totalPage,
        "records": data
}

最后点击界面上的保存按钮,即可将接口保存到数据库中。

通过上面的步骤,即完成了一个分页查询的接口,没有去写Mapper、BO、VO、DO、DAO、Service、Controller 等J ava 类,大大提升了接口的开发效率。
 

最后

优点

  1. 在线配置接口,无需编写 java 代码
  2. 明显提升接口开发效率,无需编写 Mapper、BO、VO、DO、DAO、Service、Controller 等 Java 类
  3. 数据聚合方便

待解决问题

当前 Dataway 版本:4.1.7,后续升级可能解决下面的问题

  1. 参数校验
  2. 鉴权 - 官方有提供拦截器,但是似乎不好与 shiro 进行整合
  3. 对其他数据库的支持不够友好,例如:Redis、MongoDB(需要自己实现)

链接

官网:https://www.hasor.net/web/dataway/index.html
知乎专栏:https://zhuanlan.zhihu.com/hasor

最后更新 2021-06-02
评论 ( 0 )
OωO
隐私评论