SpringBoot整合Hasor实践入坑指南

一、前言

某日赵某下班乘坐地铁刷某乎时发现一篇文章,差不多标题的意思是再也不用再项目中写Controller、Service以及Dao了,这题目很是吸引人啊,一般这样的文章下面都会有人在那讨论。正好闲来无事,我也看了看官方文档,结合当前工作的实际需要写了一个小项目。

二、了解一下Hasor:

先给出大家官方网站地址,毕竟官方的才是最权威的。
Hasor官方文档
Hasor有着自己的独立的生命周期与Spring的不同,是一套完整的体系,最低环境要求是JDK1.8,所以说这个东西很新,提供了注入DataQL、Dataway、hasor-web等等,让你的代码无需在写Controller、Service、Dao、BO、VO、mapper等等东西,这是一个数据聚合项目,有优点也有不足,主要看具体的需求环境是否合适,合适的才是最好的!
我为什么要用Hasor写一个的demo呢?我的需求场景:工作有一套系统对接了一个项目A,项目A会将数据推送到我们这里,我们对数据进行校验并保存请求记录,如果通过了我们的校验,我们在将数据封装推送给另一个项目C。我们的角色有点网关的意思哈,当然这个数据传输过程中的数据交换格式,以及数据内容什么的会发生一些变化。这个时候项目A的开发人员经常会询问我是否已经将数据推送给项目C,每次都需要我打开数据库,写上两行SQL去查询我们数据库中关于这条数据的状态是否已经成功推送到项目C;这是一种及其无聊且没有难度的重复性活动,我怎么会一直手动去数据库中一直给他查数据状态。这个时候的我就看上了Hasor中不用写Controller、service、dao以及各种model、mapper,我想要的只不过是将我在数据库查询到的结果反馈给项目A的开发人员即可。

三、创建一个SpringBoot项目,添加Hasor依赖

创建一个简单的SpringBoot项目,然后在Maven中添加hasor-spring连通Hasor和Spring,使得能够在SpringBoot中使用hasor,添加hasor-dataway让我们能够不用写Controller这些东西而通过页面配置接口的方式将数据和接口设计出来;一个Jdbc连接,用于连接Mysql数据库,注意使用Hasor-dataway必须使用数据库,配置也必须在数据库中配置两个表。

项目的Maven依赖如下:(以下依赖最好使用Hasor的最新版本,现在迭代速度还是很快的,旧版本可能会存在一些问题)

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--Spring-web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--连通 Spring 和 Hasor-->
        <dependency>
            <groupId>net.hasor</groupId>
            <artifactId>hasor-spring</artifactId>
            <version>4.1.7</version>
        </dependency>
        <!--DataWay 是Hasor生态中的一员-->
        <dependency>
            <groupId>net.hasor</groupId>
            <artifactId>hasor-dataway</artifactId>
            <version>4.1.7</version><!-- 4.1.4 包存在UI资源缺失问题 -->
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--JDBC-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

    </dependencies>

打开数据库,创建两个新的表,用于维护dataway的API,建表建议参考官方网站的,因为不同版本的Hasor依赖的表的字段可能是不同的。
建表语句如下(如果出现表问题,可以参照官方网站修改)

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) DEFAULT NULL COMMENT '注释',
  `api_type` varchar(24) NOT NULL COMMENT '脚本类型:SQL、DataQL',
  `api_script` mediumtext NOT NULL COMMENT '查询脚本:xxxxxxx',
  `api_schema` mediumtext COMMENT '接口的请求/响应数据结构',
  `api_sample` mediumtext COMMENT '请求/响应/请求头样本数据',
  `api_option` mediumtext 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=7 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 COMMENT '接口的请求/响应数据结构',
  `pub_sample` mediumtext COMMENT '请求/响应/请求头样本数据',
  `pub_option` mediumtext COMMENT '扩展配置信息',
  `pub_release_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '发布时间(下线不更新)',
  PRIMARY KEY (`pub_id`),
  KEY `idx_interface_release` (`pub_api_id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COMMENT='Dataway API 发布历史。';

四、整合SpringBoot和Hasor

SpringBoot整合Hasor中的dataway主要是将数据也配置到Hasor中,同时在启动入口开启Hasor和Hasor-web。整合起来也是十分的简单。

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.stereotype.Component;

import javax.sql.DataSource;

@DimModule  // Hasor 中的标签,表明是一个Hasor的model
@Component  // Spring 中的标签,表明是一个组件
public class HasorComponent implements SpringModule {

    private final DataSource dataSource;

    public HasorComponent(DataSource dataSource){
        this.dataSource = dataSource;
    }

    /**
     * Hasor 启动的时候会调用 loadModule 方法,
     * 在这里再把 DataSource 设置到 Hasor 中。
     * @param apiBinder
     * @throws Throwable
     */
    @Override
    public void loadModule(ApiBinder apiBinder) throws Throwable {
        apiBinder.installModule(new JdbcModule(Level.Full, this.dataSource));
    }

}

启动类代码如下:

import net.hasor.spring.boot.EnableHasor;
import net.hasor.spring.boot.EnableHasorWeb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 启用Hasor
 */
@EnableHasor
@EnableHasorWeb  // 将 hasor-web 配置到 Spring 环境中,Dataway 的 UI 是通过 hasor-web 提供服务。
@SpringBootApplication
public class QueryApplication {
    public static void main(String[] args) {
        SpringApplication.run(QueryApplication.class, args);
    }
}

application.yml文件(主要是开启和配置Dataway)配置如下:

server:
  port: 9800

spring:
  profiles:
    active: dev
# 是否启用 Dataway 功能(必选:默认false)
HASOR_DATAQL_DATAWAY: true

# 是否开启 Dataway 后台管理界面(必选:默认false)
HASOR_DATAQL_DATAWAY_ADMIN: true

# dataway  API工作路径(可选,默认:/api/)
HASOR_DATAQL_DATAWAY_API_URL: /interface/

# dataway-ui 的工作路径(可选,默认:/interface-ui/)
HASOR_DATAQL_DATAWAY_UI_URL: /config/

# SQL执行器方言设置(可选,建议设置)
HASOR_DATAQL_FX_PAGE_DIALECT: mysql

application-dev.yml配置文件如下(主要是配置数据源):

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

项目的代码编程语配置就好了,下面就可以启动程序了,因为我们后面想从数据库中拿取数据,就可以在页面中编辑就行了。
四、配置数据接口
在程序正常启动以后,在浏览器中打开DatawayAPI的配置页面,因为我在application.yml文件修改了默认UI页面地址,自己和自己的对应上就好了,地址:http://127.0.0.1:9800/config/
这里注意一下地址后面的/也要有,第一次打开会慢一点。打开后DatawayAPI配置页面如下图:
在这里插入图片描述
为了演示效果,我新建一个了animal表作为演示用,里面的inputtime和updatetime主要用于演示DataQL,建表语句如下:

CREATE TABLE `animal` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `name` varchar(20) NOT NULL COMMENT '动物名称',
  `alias` varchar(40) NOT NULL COMMENT '动物别名',
  `description` varchar(300) DEFAULT '' COMMENT '动物描述',
  `inputtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '动物信息入机时间',
  `updatetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '动物信息更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

插入几条测试数据:

INSERT INTO animal (name,alias,description) VALUES ('西伯利亚猩猩','黑猩猩','西伯利亚');

INSERT INTO animal (name,alias,description) VALUES ('东北虎','大脑虎','东北地区');

INSERT INTO animal (name,alias,description) VALUES ('孔雀','白孔雀','北京动物园');

INSERT INTO animal (name,alias,description) VALUES ('狮子','辛巴','影视');

INSERT INTO animal (name,alias,description) VALUES ('边境牧羊犬','边牧','家中');

INSERT INTO animal (name,alias,description) VALUES ('西伯利亚雪橇犬','二哈','富足家庭中');

INSERT INTO animal (name,alias,description) VALUES ('蓝猫','猫','家养');

INSERT INTO animal (name,alias,description) VALUES ('大熊猫','国宝','北京动物园');

测试数据如下:
在这里插入图片描述

五、新建一个Dataway接口

首先介绍一些Dataway的基本知识,Dataway可以通过UI页面定义数据接口,然后通过自测和冒烟以后才能发布这个接口,当接口发布成功以后,就可以通过我们定义的接口路径来访问获取数据了,这些接口数据都是保存在我们上面创建的interface_info表中的,当然接口发布以后也可以修改,也即接口可以有历史版本,这些信息保存在interface_release 表中,这也就是为什么我们什么要在上面定义这两个表;(Ps:当然Dataway也可以通过编写代码来实现)在Dataway的数据访问中使用的是一种名字叫做DataQL的脚本语言,类似JavaScript 先来一段官网的说明定义:
DataQL(Data Query Language)DataQL 是一种查询语言。旨在通过提供直观、灵活的语法来描述客户端应用程序的数据需求和交互。

数据的存储根据其业务形式通常是较为简单的,并不适合直接在页面上进行展示。因此开发页面的前端工程师需要为此做大量的工作,这就是 DataQL 极力解决的问题。另外还支持使用SQL来,但是SQL在Dataway中最终也都是转换成DataQL。
在这里插入图片描述
Dataway页面说明:
1、功能按钮:可以查看所有已经发布的接口
2、功能按钮:可以创建新的接口
3、链接:打开DataQL接口说明
4、请求方式:Http请求方式定义,默认是POST方法
5、接口路径:定义接口的请求路径,/interface/为配置文件中HASOR_DATAQL_DATAWAY_API_URL属性事先定义的值,后面补充路径,当接口路径发布后,后面定义的接口请求路径不能重名
6、接口说明:可以为接口添加中文说明
7、使用DataQL编写接口,默认选择为DataQL
8、使用SQl编写接口
9、接口编写代码部分
10、功能按钮:保存9部分编写的代码,注意只有先保存才能进行冒烟测试
11、功能按钮:测试按钮,当编写接口代码时,使用此按钮进行接口测试
12、功能按钮:冒烟测试按钮,通过了冒烟测试以后才能发布
13、功能按钮:发布接口,发布接口以后以后就可以通过发布的接口获取数据
14、功能按钮:接口编辑历史记录,可以通过历史记录回滚9区域的代码
15、功能按钮:删除按钮,点击删除后删除已经发布的接口(数据库中也会清除这条记录)
16、18功能区域:这个区域可以设置接口的请求参数例如通过POST方法传输一个请求报文,在此区域定义
17、功能按钮:设置接口的请求头参数
19、功能区域:测试接口区域,点击11测试按钮或者12冒烟以后在此区域显示测试结果
1)在介绍完了页面的基本功能以后,新建一个请求接口。
在页面中点击【new】新建一个数据接口,请求方式设置为【GET】方法,路径为【querytest】,接口说明为【请求接口GET方法测试】,选择使用【DataQL】开发(功能会更强大一点),编写代码部分的主要功能为查询数据中动物表(animal)中的(name)字段中包含犬的数据,接口参数设置为【name】传输要查询包含某个字的动物数据代码如下:

// 查询动物表中名字中包含犬的数据

// 定义一个函数,将函数的查询结果存贮在querydog中
// @@sql()为插入外部SQL代码,<%  %>为SQl代码区域
// name为函数的参数,如果想要在SQL使用这个参数,需要使用#{name}来使用
// #,$,@都为特殊符号,一般情况下用法一致,更多用法可参考官方说明
var querydog = @@sql(name)<%
    select * from animal where name like #{name}
%>

// 返回上述SQL查询到的数据
// 通过$获取Parameters中的传过来的name 参数值

return querydog(${name});

在这里插入图片描述
我们在接口返回中可以看见我们创建的animal表中的动物信息入机时间和更新时间都是时间戳,我们通过DataQL查询出来的也为时间戳,这个时候我们就可以借助DataQL的函数对数据进行一个转换
,与此同时,我们还可以借助lambda解析数据,将代码改为如下:

// 查询动物表中名字中包含犬的数据

// 定义一个函数,将函数的查询结果存贮在querydog中
// @@sql()为插入外部SQL代码,<%  %>为SQl代码区域
// name为函数的参数,如果想要在SQL使用这个参数,需要使用#{name}来使用
// #,$,@都为特殊符号,一般情况下用法一致,更多用法可参考官方说明
var querydog = @@sql(name)<%
    select * from animal where name like %#{name}%
%>

// 返回上述SQL查询到的数据
// 通过$获取Parameters中的传过来的name 参数值
// 修改返回报文中的将id换成编号,name 换成动物名称  诸如此类......
// 查询到的数据包含多个对象,注意格式  [{}],不然只显示一个
return querydog(${name})=>[{
    "编号":id,
    "动物名称":name,
    "动物别名":alias,
    "动物描述":description,
    "动物信息入机时间":inputtime,
    "动物信息更新时间":updatetime
}]

运行效果如下图:
在这里插入图片描述
添加DataQL中的FunctionX函数将时间戳改为我们指定格式时间格式,首先需要引入日期这个函数,as的作用相当于起一个别名来使用这个函数:

import 'net.hasor.dataql.fx.basic.DateTimeUdfSource' as time;

在返回数据调用format方式格式化时间如下:

// 定义一个处理updatetime日期格式的函数
var formatupdatetime = (updatetime)->{
    return time.format(updatetime, "yyyy-MM-dd HH:mm:ss")
}

// 返回上述SQL查询到的数据
// 通过$获取Parameters中的传过来的name 参数值
// 修改返回报文中的将id换成编号,name 换成动物名称  诸如此类......
// 查询到的数据包含多个对象,注意格式  [{}],不然只显示一个
// 调用日期函数,将Long类型的时间戳输出为格式化的时间
// dang然也可以定义一个函数来进行处理,如上的formatupdatetime函数
return querydog(${name})=>[{
    "编号":id,
    "动物名称":name,
    "动物别名":alias,
    "动物描述":description,
    "动物信息入机时间":time.format(inputtime, "yyyy-MM-dd HH:mm:ss"),
    "动物信息更新时间": formatupdatetime(updatetime)
}]

最后的整体代码如下:

import 'net.hasor.dataql.fx.basic.DateTimeUdfSource' as time;
// 查询动物表中名字中包含犬的数据


// 定义一个函数,将函数的查询结果存贮在querydog中
// @@sql()为插入外部SQL代码,<%  %>为SQl代码区域
// name为函数的参数,如果想要在SQL使用这个参数,需要使用#{name}来使用
// #,$,@都为特殊符号,一般情况下用法一致,更多用法可参考官方说明
var querydog = @@sql(name)<%
    select * from animal where name like #{name}
%>

// 定义一个处理updatetime日期格式的函数
var formatupdatetime = (updatetime)->{
    return time.format(updatetime, "yyyy-MM-dd HH:mm:ss")
}

// 返回上述SQL查询到的数据
// 通过$获取Parameters中的传过来的name 参数值
// 修改返回报文中的将id换成编号,name 换成动物名称  诸如此类......
// 查询到的数据包含多个对象,注意格式  [{}],不然只显示一个
// 调用日期函数,将Long类型的时间戳输出为格式化的时间
// dang然也可以定义一个函数来进行处理,如上的formatupdatetime函数
return querydog(${name})=>[{
    "编号":id,
    "动物名称":name,
    "动物别名":alias,
    "动物描述":description,
    "动物信息入机时间":time.format(inputtime, "yyyy-MM-dd HH:mm:ss"),
    "动物信息更新时间": formatupdatetime(updatetime)
}]

在这里插入图片描述
至此我们通过GET方法查询动物表中动物名称包含有犬的功能接口就开发完了,点击保存按钮进行保存,点击冒烟测试按钮进行测试,点击发布按钮进行发布。发布成功以后,我们就可以通过定义的API直接获取数据了,而不需要进行Controller、service、dao、Mapper等的书写;
在这里插入图片描述
然后我们在浏览器中直接输入已经发布的API ,测试能否获取我们预想的数据;
注意这里我们设置成GET请求方式,需要的入参为name的值,请求路径应如:http://127.0.0.1:9800/interface/querytest?name=%犬%
这与POST请求方式不同;(这里的接口设计是有一定问题的,我们为了模糊查询在参数中传入了%,中文转码以后会有冲突,可以换成数据库name为边境牧羊犬进行查询或者使用Postman传参)
在这里插入图片描述
使用Postman的测试结果如下:
在这里插入图片描述

六、新建一个POST 接口与GET接口进行比较

之所以要进行POST接口与GET接口的请求比较主要是因为POST的入参方式和GET方式的不同,究其根本其实也就是POST与GET方法的区别;我们还是复用上面的那个已经写好了的接口,但是定义成POST请求方式;
在这里插入图片描述
这里就没有办法通过浏览器来测试接口的返回数据了,因为浏览器默认使用的是GET方法,这里我们使用Postman进行测试;
在这里插入图片描述
这就是GET方法的API和POST方法API的区别,当然更多玩法可以参看官方文档:Hasor官方文档

七、总结

总结一下,个人觉得Hasor还是有很多优点的,例如可以和方便的与SpringBoot结合,可以不用写Controller、service、dao、mapper这一套东西,可以动态修改配置API等等;但是缺点也是有的,个人觉得这东西还很年轻,有一定的学习成本(例如要学习DataQL)等等这些。我之所以写这篇博客是因为现在的Hasor更好符合我的需求。
有兴趣的小伙伴可以关注微信公众号【为码以梦】,更方便看文

在这里插入图片描述

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
<p>Hasor开发框架是一款基于Java语言的应用程序开发框架,它的核心设计目标是提供一个简单、切必要的环境给开发者。开发者可以在此基础上,通过Hasor强有力的粘合机制,构建出更加完善的应用场景。同时Hasor的各种内置插件也会帮助开发者进行快速开发。 基于目前Hasor内核上已经发展出DB、Web、Restful三大独立的基础框架。</p><p>特征: 1、IoC/Aop编程模型,设计精巧,使用简单 2、COC原则的最佳实践,‘零’配置文件 3、微内核 + 扩展,基于内核已发展出DB、Web、Restful三大独立的基础框架 4、真正的零开发,解析项目特有的自定义Xml配置 5、支持模板化配置文件,程序打包之后一套配置通吃(日常、预发、线上)以及其它各种环境 6、完备的JDBC操作接口,支持Result -> Object映射 7、提供三种途径控制事务,支持七种事务传播属性,标准的事务隔离级别 8、支持多数据源、及多数据源下的事务控制(非JPA) 9、内置事件机制,方便进行业务深度解耦,使业务逻辑更佳清晰 10、支持Web类型项目开发,提供restful风格的mvc开发方式 11、支持Form表单验证、支持场景化验证 12、提供开放的模版渲染接口,支持各种类型的模版引擎 13、提供丰富的工具箱,帮助您快速开发,有了它您甚至不需要 apache-commons 14、支持log4j、logback等多种主流日志框架 15、体积小,无第三方依赖</p><p>最低要求: 1、jdk6 2、servlet 2.3</p>
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喵喵@香菜

感谢观众老爷送的一发火箭!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值