项目的地址是: https://github.com/yuanxinyu/kaola
Kaola(考拉,英文 koala)是一个全自动的 restful api 代码自动生成系统。给定一个数据库,只需要配置好数据库连接,koala 可以通过扫描数据库自动生成全套的 restful api 的后端代码。通过预先约定好的接口调用规范,前端就可以直接开发应用系统了。
类似 koala 的代码生成系统之前也有很多,比如 rails 自带的 scaffold 功能,以及更完善的 Active Admin/Rails Admin 等。但是这些系统都有两点不符合要求:
所以我开发了这套 koala 系统,它的主要特点是:
当然,还有一点很重要的,就是定义了一套 restful 的基于约定的接口协议。基于这套约定的协议,前端程序员不需要后端提供繁琐的不一致接口文档,可以轻松上手开始使用这套接口。
Kaola 生成的 Api 接口是基于 http 的 web 接口,URL 的命名基本沿用 rails 框架的命名约定,其中的表名都是复数形式。基本的 CRUD 接口的约定如下:
操作 | HTTP Method | URI |
---|---|---|
获取列表数据 | GET | /表名 (.:format) |
添加新数据 | POST | /表名 (.:format) |
修改已有数据 | PUT | /表名/:id(.:format) |
查看已有数据 | GET | /表名/:id(.:format) |
删除已有数据 | DELETE | /表名/:id(.:format) |
这只是对单表资源的 CRUD 操作,koala 针对下列情况也定义了一套的 Restful 规范:
Kaola 的查询参数一一对应到数据库中的字段,格式是通过把 json 格式的查询参数扁平化得来的。比如下面的查询条件,
{
"s" : {
gender : 'm',
"like" : {
name : 'b'
}
},
"order" : "id asc"
}
它的含义是查找所有 gender 等于'm'并且 name 包含'b'的记录,按'id asc'排序,扁平化以后就是:
s[gender]=m&s[like[name]]=b&order=id asc
如果表的名字是‘users’,那么请求‘users.json?s[gender]=m&s[like[name]]=b&order=id+asc’就可以得到所有符合条件的 json 格式的数据。
针对查询/分页/排序/批量操作/关联表操作/导入导出等的具体的约定(前端开发者需要细看)可以参考:
Kaola 是基于 ruby on rails 开发的,主要在 Mac 和 Linux 操作系统下完成开发 ,数据库使用的是 mysql。如果你的操作系统是 windows,或者数据库不是 mysql,大体上是兼容的,但可能会碰到问题。
安装 ruby2.2 以上版本,如何安装可参考这个链接。安装完成 ruby 以后,在命令行运行”gem install bundle”以安装 bundle;
下载 koala 的代码,在项目根目录运行“bundle install”安装依赖的第三方库;
配置数据库连接,具体参考数据库配置;
在项目的根目录运行“./autogen.sh”,自动生成所有的后端 api 代码;
启动 api 服务器,在开发环境下就是运行“rails server”
然后打开浏览器访问这个链接就可以看到生成的所有接口了。在开发环境下,koala 除了 api 接口,也提供完整的 CRUD 的 html 页面(其实就是 rails 默认的 scaffold 生成的页面)。在发布环境下,只有接口调用可以访问,基本就是以".json"结尾的 url 访问。
扫描数据库实现所有单表的 CRUD 功能接口,这个不难实现。比较难的是怎么处理数据关联关系。数据关联关系主要有三种:一对多,一对一,多对多。Kaola 在实现关联关系的时候,分两个阶段实现的。
第一个阶段,在 2016 年项目最初开发的时候,只支持一对多关系。一对一关系是一对多关系的特例,而多对多关系则可以表示为两个一对多关系,所以只支持一对多关系也不算严重的缺陷。
那么如何自动发现数据库所有的一对多关系呢,主要通过三种方法:
3.通过配置文件。有些遗留的数据库即没有配置外键,也不符合命名约定,那么在配置文件 custom_fk.txt 文件中配置好外键关系也可以。
关联关系是双向的,对于两个表 table1s 和 table2s,如果 table1 有一个字段 table2_id,那么 table1 是多方,table2 是一方,用 rails 来描述就是:
Table1 belongs_to table2
Table2 has_many table1s
第二个阶段是 2017 年,kaola 开发完成接近一年的时候,有个项目组提出要多对多关系的支持,在压力下想明白了多对多关系。首先,rails 支持两种多对多关系:直接式的“has_and_belongs_to_many”和间接式的“has_many through”, 对应的例子见下图:
Rails 已经不建议使用直接式的多对多关系参考,Kaola 也不支持这种方式。下面就是自动发现多对多关联的最关键一步:所有包含两个及以上外键(也包括命名约定/配置文件定义的外键)的表自动形成多对多关系。一张表有 2/3/4 个外键,分别会定义 1/2/6 个多对多关系,也就是给定 n 个外键,生产组合 C(2,n) 个多对多关系。
除了常规的三种关系,还有一种特殊的自引用关系:树形结构。树形结构最常见的例子有组织结构、产品类别等。为了存储树形结构,要求给定的表有一个指向自己的外键。外键值为空的节点是树的根节点。树形结构在 kaola 中被定义为一个指向自己的一对多关系。
识别了这些常见的数据关联关系后,接下来的任务是如何支持对这些关系的增删改查操作。目前对关系数据的增删改还只支持一对多关系,不支持多对多关系。 由于 kaola 采用 json 格式提交数据,所以新增和修改有关系的数据是比较容易的,json 格式很容易支持用嵌套结构来表达一对多关系。比如单个新增的话,提交的是一个 hash 对象
{
"表名单数": {id:id, key:value,...}
}
那么对于一次性提交主子表的数据,格式就是
{
"主表单数": {id:id, key:value,...},
"子表复数": [
{id:id, key:value,...},
{id:id, key:value,...}
],
其它子表...
}
下一步是如何定义和实现关联关系的查询。Kaola 使用了面向对象语言的“.”操作符来表达主子表的关系,从而可以达到比 sql 语句更简单自然的查询表达式。比如有两张表:公司表 companies 和仓库表 warehouses,一个公司可以有 多个仓库,那么下面的查询
warehouses.json?s[company.name]='公司 A'
表示查询所有的 name 为‘公司 A’的公司所有的仓库。对应的 Sql 查询是:
select * from warehouses join companies on warehouses.company_id = companies.id where companies.name='公司 A'
关联表的查询支持所有单表查询的功能,包括等于/Like/日期/数值范围/枚举查询。 此外,针对一对多关系,还支持两种特殊的查询:Exists 查询(给定主表是否有子表数据)和树形结构查询(给定数据节点的所有深层嵌套子节点)。
具体的技术实现细节可以参考:
Kaola 主要的使用场合是内部 IT 系统的后端,比如各类管理后台、各类信息管理系统(CRM/SCM/ERP/HIS)等。
Kaola 最初的场景是用在一个供应链系统中。这个系统有几百张表,表间的关联复杂。应用 Kaola 后,整个后端代码量大大减少,所有增删改查的 api 都是自动生成的。最后只有三个文件,几百行代码是需要为供应链的逻辑定制的。这三个文件分别处理各类订单流水号生成逻辑、库存计算逻辑、订单流转逻辑。这些逻辑都是通过 rails 的数据库钩子实现的,不修改自动生成的代码,所以维护也很方便。比如下面就是序列号生成逻辑/订单流转逻辑的模版代码。
class ActiveRecord::Base
before_validation :gen_seq
def gen_seq
#序列号生成逻辑
end
end
class ActiveRecord::Base
before_update :order_process
def order_process
#订单流转逻辑
end
end
如果你的团队后端有 ruby 程序员,这是推荐使用 kaola 的方式,增删改查的 api 用 kaola 自动生成,其它的功能通过修改 kaola 的代码实现。
如果你的团队后端没有 ruby 程序员,也可以使用 kaola 来帮助减少后端的开发工作量。通过采用前后端分离架构,前端开发其实不关心后端的 api 是用什么语言实现的。
我们在一个健康干预系统项目中采用了混合语言后端的案例。这个项目组都是 java 后端程序员,通过 kaola 来帮助 java 程序员完成增删改查的 api,而健康干预计划/健康报告生成等功能则是独立部署的 java 后端实现的。
由于 kaola 提供 api 接口能力太广泛,不能直接暴露在网络上。所以在发布的时候,需要部署在一个 api 网关后面,比如 Netflix/zuul 这样的网关。
Kaola 采用 MIT License, https://opensource.org/licenses/MIT
俗话说,懒惰是程序员的美德,能够让计算机自动完成的事情,就不要重复劳动了。取名 Kaola 是希望这套系统让程序员可以像考拉一样悠闲,同时 restful 也有宁静的含义,和考拉的形象比较匹配。
2016 年在高可用架构社区做的一次技术分享: