Skip to content
master
Go to file
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
app
 
 
bin
 
 
 
 
db
 
 
doc
 
 
lib
 
 
log
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Readme.md

一个超酷的Restful Api自动生成器:Kaola

0. 什么是Kaola

Kaola(考拉,英文koala)是一个全自动的restful api代码自动生成系统。给定一个数据库,只需要配置好数据库连接,koala可以通过扫描数据库自动生成全套的restful api的后端代码。通过预先约定好的接口调用规范,前端就可以直接开发应用系统了。

1. 为什么开发Kaola

类似koala的代码生成系统之前也有很多,比如rails自带的scaffold功能,以及更完善的Active Admin/Rails Admin等。但是这些系统都有两点不符合要求:

  1. 这些系统都是一套完整的系统,从后端到页面都一次性生成。实际的情况是,后端的接口比较通用,而界面和操作流程往往需要深度的定制。修改这些系统自动生成的页面是很困难的。
  2. 这些系统往往都是只支持单表CRUD操作,对多表之间的关联操作支持不够。

所以我开发了这套koala系统,它的主要特点是:

  1. 只提供后端的restful api接口,前端的代码还是需要每个应用自己编写,采用前后端分离架构;
  2. 接口不仅支持常规的单表CRUD操作,还自动支持多表关联(一对多、多对多、自引用的树形结构),支持复杂的查询(分页、排序、计数、索引)、支持批量操作、以及拥有一套透明高效的缓存体系。

当然,还有一点很重要的,就是定义了一套restful的基于约定的接口协议。基于这套约定的协议,前端程序员不需要后端提供繁琐的不一致接口文档,可以轻松上手开始使用这套接口。

2. Kaola的接口协议约定

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规范:

  1. 查询/分页/排序的支持。 标准Restful接口只有一个列表的接口,对查询相关的功能没有约定,koala自行扩展了一套约定。
  2. 批量操作的支持。 Restful接口默认只支持单个资源的操作,而实际的业务场景中经常需要有批量操作的需求,比如商品的批量上架、数据的批量删除等。
  3. 有关联的数据表的支持。Restful只支持单个资源的CRUD,而实际业务中经常有主子表的级联保存,关联表的查询等。

查询的约定

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格式的数据。

针对查询/分页/排序/批量操作/关联表操作/导入导出等的具体的约定(前端开发者需要细看)可以参考:

3. 开始使用Kaola

Kaola是基于ruby on rails开发的,主要在Mac和Linux操作系统下完成开发 ,数据库使用的是mysql。如果你的操作系统是windows,或者数据库不是mysql,大体上是兼容的,但可能会碰到问题。

  1. 安装ruby2.2以上版本,如何安装可参考这个链接。安装完成ruby以后,在命令行运行”gem install bundle”以安装bundle;

  2. 下载koala的代码,在项目根目录运行“bundle install”安装依赖的第三方库;

  3. 配置数据库连接,具体参考数据库配置

  4. 在项目的根目录运行“./autogen.sh”,自动生成所有的后端api代码;

  5. 启动api服务器,在开发环境下就是运行“rails server”

然后打开浏览器访问这个链接就可以看到生成的所有接口了。在开发环境下,koala除了api接口,也提供完整的CRUD的html页面(其实就是rails默认的scaffold生成的页面)。在发布环境下,只有接口调用可以访问,基本就是以".json"结尾的url访问。

4. 实现原理

扫描数据库实现所有单表的CRUD功能接口,这个不难实现。比较难的是怎么处理数据关联关系。数据关联关系主要有三种:一对多,一对一,多对多。Kaola在实现关联关系的时候,分两个阶段实现的。

识别一对多关系

第一个阶段,在2016年项目最初开发的时候 ,只支持一对多关系。一对一关系是一对多关系的特例,而多对多关系则可以表示为两个一对多关系,所以只支持一对多关系也不算严重的缺陷。

那么如何自动发现数据库所有的一对多关系呢,主要通过三种方法:

  1. 通过数据库的外键。如果A表有一个外键指向B表,那么B表和A表就是一对多关系。
  2. 通过命名约定。外键的命名约定采用rails默认的约定,外键的名字都是“表名单数_id”。同时对 rails的约定有扩展,如果一张表里有多个关联到另外一张表的外键,命名规则是“前缀_表名单数_id”。所有符合命名约定的表,即使没有设置数据库层的外键,也自动建立一对多关系。 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”, 对应的例子见下图:

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查询(给定主表是否有子表数据)和树形结构查询(给定数据节点的所有深层嵌套子节点)。

具体的技术实现细节可以参考:

5. 案例

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后端实现的。

6. 杂项

发布

由于kaola提供api接口能力太广泛,不能直接暴露在网络上。所以在发布的时候,需要部署在一个api网关后面,比如Netflix/zuul这样的网关。

License

Kaola采用 MIT License, https://opensource.org/licenses/MIT

为何取名Kaola

俗话说,懒惰是程序员的美德,能够让计算机自动完成的事情,就不要重复劳动了。取名Kaola是希望这套系统让程序员可以像考拉一样悠闲,同时restful也有宁静的含义,和考拉的形象比较匹配。

去年的技术分享

2016年在高可用架构社区做的一次技术分享:

About

A Restful API Server For Database

Resources

Releases

No releases published

Packages

No packages published
You can’t perform that action at this time.