SpringBoot三十五:整合Dataway

Dataway介紹

Dataway 是基於 DataQL 服務聚合能力,爲應用提供的一個接口配置工具。使得使用者無需開發任何代碼就配置一個滿足需求的接口。整個接口配置、測試、冒煙、發佈。一站式都通過 Dataway 提供的 UI 界面完成。UI 會以 Jar 包方式提供並集成到應用中並和應用共享同一個 http 端口,應用無需單獨爲 Dataway 開闢新的管理端口。

這種內嵌集成方式模式的優點是,可以使得大部分老項目都可以在無侵入的情況下直接應用 Dataway。進而改進老項目的迭代效率,大大減少企業項目研發成本。

Dataway 工具化的提供 DataQL 配置能力。這種研發模式的變革使得,相當多的需求開發場景只需要配置即可完成交付。從而避免了從數據存取到前端接口之間的一系列開發任務,例如:Mapper、BO、VO、DO、DAO、Service、Controller 統統不在需要。

Dataway 是 Hasor 生態中的一員,因此在 Spring 中使用 Dataway 首先要做的就是打通兩個生態。根據官方文檔中推薦的方式我們將 Hasor 和 Spring Boot 整合起來。這裏是原文:https://www.hasor.net/web/extends/spring/for_boot.html

第一步:引入相關依賴

<dependency>
	<groupId>net.hasor</groupId>
	<artifactId>hasor-spring</artifactId>
	<version>4.1.3</version>
</dependency>
<dependency>
	<groupId>net.hasor</groupId>
	<artifactId>hasor-dataway</artifactId>
	<version>4.1.3-fix20200414</version><!-- 4.1.3 包存在UI資源缺失問題 -->
</dependency>

hasor-spring 負責 Spring 和 Hasor 框架之間的整合。
hasor-dataway 是工作在 Hasor 之上,利用 hasor-spring 我們就可以使用 dataway了。

第二步:配置 Dataway,並初始化數據表

dataway 會提供一個界面讓我們配置接口,這一點類似 Swagger 只要jar包集成就可以實現接口配置。找到我們 springboot 項目的配置文件 application.properties

# 是否啓用 Dataway 功能(必選:默認false)
HASOR_DATAQL_DATAWAY=true

# 是否開啓 Dataway 後臺管理界面(必選:默認false)
HASOR_DATAQL_DATAWAY_ADMIN=true

# dataway  API工作路徑(可選,默認:/api/)
HASOR_DATAQL_DATAWAY_API_URL=/api/

# dataway-ui 的工作路徑(可選,默認:/interface-ui/)
HASOR_DATAQL_DATAWAY_UI_URL=/interface-ui/

# SQL執行器方言設置(可選,建議設置)
HASOR_DATAQL_FX_PAGE_DIALECT=mysql

Dataway 一共涉及到 5個可以配置的配置項,但不是所有配置都是必須的。

其中 HASOR_DATAQL_DATAWAY、HASOR_DATAQL_DATAWAY_ADMIN 兩個配置是必須要打開的,默認情況下 Datawaty 是不啓用的。

Dataway 需要兩個數據表才能工作,下面是這兩個數據表的簡表語句。下面這個 SQL 可以在 dataway的依賴 jar 包中 “META-INF/hasor-framework/mysql” 目錄下面找到,建表語句是用 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_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_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);

第三步:配置數據源

作爲 Spring Boot 項目有着自己完善的數據庫方面工具支持。我們這次採用 druid + mysql + spring-boot-starter-jdbc 的方式。

首先引入依賴

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid</artifactId>
	<version>1.1.21</version>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>druid-spring-boot-starter</artifactId>
	<version>1.1.10</version>
</dependency>

然後增加數據源的配置

# db
spring.datasource.url=jdbc:mysql://localhost:3306/javakf_test1?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
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

如果項目已經集成了自己的數據源,那麼可以忽略第三步。

第四步:把數據源設置到 Hasor 容器中

Spring Boot 和 Hasor 本是兩個獨立的容器框架,我們做整合之後爲了使用 Dataway 的能力需要把 Spring 中的數據源設置到 Hasor 中。

首先新建一個 Hasor 的 模塊,並且將其交給 Spring 管理。然後把數據源通過 Spring 注入進來。

@DimModule
@Component
public class DatawayModule 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));
	}

}

Hasor 啓動的時候會調用 loadModule 方法,在這裏再把 DataSource 設置到 Hasor 中。

第五步:在SprintBoot 中啓用 Hasor

@EnableHasor()
@EnableHasorWeb()
@SpringBootApplication(scanBasePackages = { "cn.com.javakf.dataway" })
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

這一步非常簡單,只需要在 Spring 啓動類上增加兩個註解即可。

第六步:啓動應用

應用在啓動過程中會看到 Hasor Boot 的歡迎信息

 _    _                        ____              _
| |  | |                      |  _ \            | |
| |__| | __ _ ___  ___  _ __  | |_) | ___   ___ | |_
|  __  |/ _` / __|/ _ \| '__| |  _ < / _ \ / _ \| __|
| |  | | (_| \__ \ (_) | |    | |_) | (_) | (_) | |_
|_|  |_|\__,_|___/\___/|_|    |____/ \___/ \___/ \__|

在後面的日誌中還可以看到類似下面這些日誌。

2020-06-05 16:16:25.973  INFO 13000 --- [           main] net.hasor.dataway.config.DatawayModule   : dataway api workAt /api/
2020-06-05 16:16:25.974  INFO 13000 --- [           main] n.h.c.environment.AbstractEnvironment    : var -> HASOR_DATAQL_DATAWAY_API_URL = /api/.
2020-06-05 16:16:25.983  INFO 13000 --- [           main] net.hasor.dataway.config.DatawayModule   : dataway self isolation ->net.hasor.dataway.config.DatawayModule
2020-06-05 16:16:25.986  INFO 13000 --- [           main] net.hasor.dataway.config.DatawayModule   : dataway admin workAt /interface-ui/
2020-06-05 16:16:25.999  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[54790db8a3bc4ff7bde0454ddbc68791] -> bindType 'class net.hasor.dataway.web.ApiDetailController' mappingTo: '[/interface-ui/api/api-detail]'.
2020-06-05 16:16:26.000  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[3868a79a79584668828b82970c657454] -> bindType 'class net.hasor.dataway.web.ApiHistoryListController' mappingTo: '[/interface-ui/api/api-history]'.
2020-06-05 16:16:26.000  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[8b6a44698e644b3ab4cb9a57bbe8a928] -> bindType 'class net.hasor.dataway.web.ApiInfoController' mappingTo: '[/interface-ui/api/api-info]'.
2020-06-05 16:16:26.001  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[c4c17f1a3fc94a8793336fb4ee19907c] -> bindType 'class net.hasor.dataway.web.ApiListController' mappingTo: '[/interface-ui/api/api-list]'.
2020-06-05 16:16:26.001  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[74580b0ecd3d4cbdb99612322dbc0836] -> bindType 'class net.hasor.dataway.web.ApiHistoryGetController' mappingTo: '[/interface-ui/api/get-history]'.
2020-06-05 16:16:26.005  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[49556cd6b6b3439992d4f7e24541e3a2] -> bindType 'class net.hasor.dataway.web.DisableController' mappingTo: '[/interface-ui/api/disable]'.
2020-06-05 16:16:26.006  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[e884cf6f7760432f9b7bdf82d8567e25] -> bindType 'class net.hasor.dataway.web.SmokeController' mappingTo: '[/interface-ui/api/smoke]'.
2020-06-05 16:16:26.007  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[4c7dd96f388043c8899ef006a8a9da7a] -> bindType 'class net.hasor.dataway.web.SaveApiController' mappingTo: '[/interface-ui/api/save-api]'.
2020-06-05 16:16:26.008  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[ba000a8dda8242228787e042d17675e0] -> bindType 'class net.hasor.dataway.web.PublishController' mappingTo: '[/interface-ui/api/publish]'.
2020-06-05 16:16:26.009  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[420123f03de04c038ebcb6f72cadefb4] -> bindType 'class net.hasor.dataway.web.PerformController' mappingTo: '[/interface-ui/api/perform]'.
2020-06-05 16:16:26.010  INFO 13000 --- [           main] net.hasor.core.binder.ApiBinderWrap      : mapingTo[a27a930c0b06441990330fd1ccd5d0da] -> bindType 'class net.hasor.dataway.web.DeleteController' mappingTo: '[/interface-ui/api/delete]'.

當看到 “dataway api workAt /api/” 、 dataway admin workAt /interface-ui/ 信息時,就可以確定 Dataway 的配置已經生效了。

第七步:訪問接口管理頁面進行接口配置

在瀏覽器中輸入 :http://127.0.0.1:8080/interface-ui/ 就可以看到期待已久的界面了。
在這裏插入圖片描述

第八步:新建一個接口

Dataway 提供了2中語言模式,我們可以使用強大的 DataQL 查詢語言,也可以直接使用 SQL 語言(在 Dataway 內部 SQL 語言也會被轉換爲 DataQL 的形式執行。)
在這裏插入圖片描述
首先我們在 SQL 模式下嘗試執行一條 select 查詢,立刻就可以看到這條 SQL 的查詢結果。
在這裏插入圖片描述
同樣的方式我們使用 DataQL 的方式需要這樣寫:

var query = @@sql()<%
    select * from interface_info
%>
return query()

其中 var query = @@sql()<% ... %> 是用來定義SQL外部代碼塊,並將這個定義存入 query 變量名中。<% %> 中間的就是 SQL 語句。

最後在 DataQL 中調用這個代碼塊,並返回查詢結果。

當接口寫好之後就可以保存發佈了,爲了測試方便,我選用 GET 方式。
在這裏插入圖片描述
接口發佈之後我們直接請求:http://127.0.0.1:8080/api/demos,就看到期待已久的接口返回值了。
在這裏插入圖片描述

最後總結

經過上面的幾個步驟我們介紹瞭如何基於 Spring Boot 項目使用 Dataway 來簡單的配置接口。Dataway 的方式確實給人耳目一新,一個接口竟然可以如此簡單的配置出來無需開發任何一行代碼,也不需要做任何 Mapping 實體映射綁定。

最後放幾個有用的連接:

原文鏈接:https://my.oschina.net/ta8210/blog/3234639

測試請求參數及數據響應格式

通常前後端連調時,都要對接一下接口。在這個過程中前後端會確定 請求參數的個數和格式,以及數據響應的個數和格式。

比如根據用戶名稱模糊查詢相關用戶列表。在這個場景中設定一個請求參數,姑且叫它 userName把。然後返回一個列表,列表中是符合條件的用戶信息。

爲了這個場景我們首先需要定義前後端交互數據接口
請求:

userName : String

響應:

rootData:Array[UserInfo]
UserInfo:{
     user_id   : Integer,
     user_name : String,
     user_sex  : String
}

在 Dataway 中首先我們新建一個接口,並且給接口取好名字和備註。
在這裏插入圖片描述
緊接着我們在 Dataway 的頁面中定義前端請求參數。
在這裏插入圖片描述
在編寫SQL 之前我們先在 DataQL 上編寫一段 JSON 通過這個 JSON 來模擬數據輸出的結果。
在這裏插入圖片描述
接下來我們編寫數據庫查詢然後返回我們在數據庫中的數據,爲了演示這個功能我在數據庫中先創建了一張表並且初始化了一些數據。

CREATE TABLE `user_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(128) DEFAULT NULL,
  `sex` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4

在這裏插入圖片描述
接下來我編寫一段 SQL 查詢這個表,並且在返回 mock 的數據的前面先嚐試執行SQL返回數據。
在這裏插入圖片描述
可以看到數據已經如我們預期的輸出了出來,在這裏 DataQL 的執行是按照順序進行的。當遇到 return 指令的時,後續的查詢將不會被執行。

接着把數據庫返回的結果做一下格式轉換,讓其按照我們要求的格式返回數據。官方手冊這一部分的內容在這裏:https://www.hasor.net/web/dataql/grammar/convert.html#
在這裏插入圖片描述
最後一部分,在 SQL 查詢中使用我們預先定義好的 userName 來進行 模糊匹配。首先 SQL 語句需要有所改寫:

select * from user_info
   =>
select * from user_info where like `name` like #{userName} <- 類似 Mybatis 的寫法,帶參數的SQL 用 #{...}

SQL 中參數名已經確定好了,接下來改寫一下 定義 SQL 查詢這一部分聲明一個參數。這就好比定義方法的參數一樣。

var query= @@sql(userName)<%   <-- 增加參數定義
    select * from user_info where `name` like #{userName}
%>

最後將前端傳入的請求參數,在執行用戶查詢的時候將其傳進去即可。在 DataQL 查詢中要想獲得 Paramerers 面板中定義的參數需要通過 ${ … } 形式獲取。這部分內容在官方手冊上也有介紹在這裏:https://www.hasor.net/web/dataql/grammar/params.html
在這裏插入圖片描述
這樣一來我們就可以通過前端傳入 '%xxxx%' 這樣的形式的參數就可以完成模糊匹配查詢了。

有心的同學可能想問如何能讓前端避免傳 % 這樣的字符? 如果傳了就默認加上,不傳就默認查詢全部。

實現這個需求其實有很多辦法,這篇文章主要講解的是前後端傳參數傳遞,因此我們選用 數據庫拼接字符串的方式來實現。

  • 我們可以利用 數據庫的字符串連接功能把 % 拼接的事情交給數據庫 : concat('%',#{userName},'%')
  • 另外還可以通過 DataQL 的方式。

然後我們在請求參數上輸入模糊匹配的信息執行查詢就可以得到結果了。
在這裏插入圖片描述
這一次我們採用 Post 方式來請求接口。爲了模擬 Post 我們需要請出 PostMan 這個神器。
在這裏插入圖片描述

代碼託管:springboot_dataway

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章