现在公司内部不同系统之间、不同公司不通系统之间需要进行数据对接的业务场景比较常见。常见的数据互通方案包括但不限于:

  • 数据库层级的互通:数据同步脚本,ETL工具,定时任务等
  • 接口层级的互通:事先约定好数据格式,然后通过HTTP/RESTFUL/MQ等手段进行数据对接。

这里第一项“数据库层级的互通”这里暂且先按下不表。今天主要想说一说接口对接的一点小想法。

通过对公司老系统以及后续较新系统的代码梳理发现,与其它系统进行接口数据对接通常采用的方式是:

  1. 根据接口文档中的定义创建接口数据实体bean对象;
  2. 根据接口文档中的定义设置好相应的请求头和请求方法;
  3. 调用通用的HTTP工具类提交数据。

思路确实是这么个思路,但是随着对接的外部接口越来越多,项目中的bean、http方法也越写越多。文件和方法写多了就会不好维护。而且若某个接口需要的参数后期变了,也需要花费较大的工作量去代码中找到对应的bean或请求方法进行相应的修改,系统的耦合性较大。

那么有没有一种解决方案,可以解除高耦合性的同时,又能很方便地对接和维护这些接口呢?

很遗憾,经过我几天的查(chao)资(zuo)料(ye)发现,目前好像并没有这么个现成的玩意儿可以被我拿来改改直接用。

本着:没有路走创造路也要走的理念,下边儿我打算用自己粗浅的知识来设计一个接口对接用的“轮子”。

一、分析业务需求

接口对接的逻辑大概如下图所示:
系统对接.png
即:A系统通过接口文档中约定的参数以及规则,向B系统推送或请求数据;B系统收到推送的数据后返回成功或失败的响应码;或者B系统收到A系统提交的请求之后,返回对应的请求资源。
通过接口对接多个系统也是同理。

二、抽象

编程的实质是抽象与表达。 将现实世界的问题抽象成容易处理的可计算对象,然后使用计算语言来实现它。

我们先将接口对接这一行为进行抽象:
对于上面的业务情况,它的主要操作无非就是将数据实体对象(bean),序列化成json(或者form表单数据),添加约定的http header,然后通过约定的http方法(post,get,put,delete等)将数据发出去,最后拿到对接服务的响应内容,然后交由业务系统进行后续处理(数据存储,失败处理,异常捕获等)。

我们再针对这个过程进行抽象:
整个过程其实就是我们需要将特定格式的JSON数据或者FORM表单数据提交给对接服务,然后拿到结果。

在这个过程中我们需要做些什么
这有点类似于:把大象装进冰箱里需要几步 的问题。这里主要步骤我觉得也是分为三步:

  1. 按照规则组装好JSON数据或者FORM表单数据
  2. 把数据发出去
  3. 处理返回的结果

三、解耦

上边叭叭叭这么多感觉其实都是废话,因为毕竟现在系统进行接口对接也是按这么个思路做的,上边谈了这么多也没有解决:既可以解除高耦合性的同时,又能很方便地对接和维护这些接口 的痛点问题。

下面我们来谈谈:如何解耦
参考一些主流做法以及设计方案,引入中间件是将两个系统之间解耦的较优解。
即:我们需要引入一个接口对接中间件,将写死在系统内部代码中的接口对接逻辑抽离出来,各系统之间不用过分在乎需要对接的系统接口是如何定义的,按照一个统一标准提交数据给中间件平台即可。借此可以达到系统解耦的目的。

四、数据管理

既然说到了在代码中管理和修改接口对象bean不方便,那怎样才能更方便?
那么将这些接口参数、header、请求方法等等信息存在数据库里面,不就方便管理了嘛!
接口参数新增、修改和删除只用在数据库里面直接增删改即可,和代码无关,根本无需重新发布新版本程序包。
妈妈再也不用担心我改了祖传代码导致系统起不来或者接口报错的问题了~

五、一些细枝末节的设计思想

  • 如何设计数据库表来存储和管理接口信息?
    一张接口信息表用于记录:接口名称、接口地址、接口描述、请求方法等
    一张接口参数表用于记录:参数名称、参数类型、参数描述、对应接口、是否是必须项等
    一张接口header表用于记录:header名称、默认值(或预设值,例如接口的Content-type预设为application/json等)、对应接口等。

接口信息表与接口参数表是一对多的关系;
接口信息表与接口header表也是一对多的关系。

  • 如何在代码中将接口数据与中间件中管理的接口信息对应?
    可以考虑给每个接口一个全局唯一的KEY名称,在代码中通过注解映射(以Java为例,其他语言可以考虑使用配置文件映射等方式)建立数据bean对象与接口的对应关系。bean对象中的各属性值按名称与接口字段对应。
    考虑到可能多个接口会对应同一个bean,以及同一个bean中的属性值可能在多个不同的接口中有用。因此这里也需要提供bean对象和接口、bean对象属性与接口字段的一对多映射关系。这个在Java代码中也可以通过注解实现(其他语言同样也可以通过配置文件等方式建立映射关系)

一个简单的一对多注解映射代码示例:
类注解.png
(bean对象上的映射注解示例)

属性注解.png
(bean属性上的映射注解示例)

使用示例.png
(一个使用示例)

然后程序内通过解析注解信息,将包含有接口信息以及值参数的JSON数据发送到接口对接中间件。

  • 接口对接中间件在接收到下游系统推送上来的数据,怎样进行解析与转发?
    在上一步中我们已经组装好了包含有:目标接口、数据实体内容的JSON数据,那么在接口对接中间件中我们仅用把这些东西解析出来即可。
    通过解析出来的接口key查询该接口定义的字段,然后以查询出来的接口字段为模板,拿着下游系统提交的数据实体内容进行值渲染,拼接成最终的,上游目标系统需要的数据格式。最后再将这些数据发送至上游目标系统,并转发目标系统的接口响应结果。

有了设计思路剩下的就是编码环节了,有时间的话再去完善一下代码,在这儿就不多赘述了。至此,一个较为通用的接口对接中间件就整完啦~
QQ图片20211209102908.jpg


摸鱼癌晚期患者