关注公众号【1024个为什么】,及时接收最新推送文章!

最近公司要新接入一个支付渠道,涉及到公司和三方的对账。由于三方对账内容格式太特殊,需要对文件解析引擎改造适配,实际改造耗时比预估的要少很多,回过头总结才发现,原来解析引擎经过前几次的迭代变得越来越易扩展,如果不是这次文件内容格式太特殊,连兼容改造都省了。

接下来就回顾一下它是如何一步步拥有今天这种能力的。

《对账中心设计与实现》这篇文章里提到,对账中心里有一个重要的组成模块就是文件解析引擎,它是驱动各对账项目的关键模块。

然而最开始,它简陋到就只有一个方法。

最开始的出发点很简单,对账所需的数据,不想直连业务的库获取,原因有三:

1、把自己的库直接暴露给其他服务,本身就是不合理设计;

2、对账属于任务性质的,瞬间请求流量上来了,搞不好会影响业务;

3、业务表结构变更后,还要跟随改动、上线。

于是就约定,参与对账的业务方,把各自每天要对账的数据放在 .txt 文件中,上传到 FTP 指定的目录。对账中心(当时还没有对账中心的概念,只是为了两个经常数据不一致的场景单独做了一个功能)从 FTP 拉取文件,每条数据解析到一个 java 对象中,再进行对象内容的比较。

这种设计也不太好,还是和业务系统间接耦合。

为了减少工作量,约定参与对账的 A、B 双方采用相同的表头,相同的分隔符,这样 A、B 就可以共用一套解析逻辑、一个 java 类暂存解析处理的内容。

解析引擎这就有了最初的雏形,然而它却差点被扼杀在摇篮之中。

这个功能上线后就暴露出好几个业务系统的 bug,给公司及时止损。对账中心也得到了重视,就推动核心的业务场景都要接进来。接了几个业务场景后发现,接入成本太高了。

业务方要开发生成对账文件,对账中心要针对每个接入的业务场景单独开发解析逻辑(因为每个业务场景文件中的字段都不一样,前面设计的是用 java 对象承载每条数据去完成比对,这样一来 java 类和对账文件一一绑定)。

于是对账中心就做了一次很大的改造,降低接入成本,适应更长远的规划。

改造后废弃了通过文件获取对账数据的模式,利用数仓直接从业务库同步所需的对账数据,数据载体也从原来的 java 对象变为由 SQL 查询结果得到的字符串,更具通用性。

与此同时,又来了新的需求,要实现公司数据和三方支付公司的对账,三方的数据都是通过三方提供的对账单下载接口下载下来的对账文件,这下数仓就不好使了吧,还是要先解析文件,这下文件解析引擎又起死回生了。

这次需求只涉及到解析微信、支付宝的对账单,而且从可预见的相当长一段时间内,不会再有其他渠道的对账单了,于是解析引擎的设计就紧紧围绕这两个渠道的文件内容展开,而且尽可能做得通用。

首先对两个渠道的文件进行全方位的对比解读:

有了这个对比,就可以抽象出变化的维度,划分出不同的功能模块,内容做成可配置的。虽然文件类型不同,但都可以直接使用 readLine() 读取每一行内容。

1、文件编码默认 UTF-8,支持配置

2、分隔符默认英文逗号,支持配置,内容中特殊字符需要额外处理,要有特殊字符处理模块

3、表头处理模块,同一类文件表头内容不同要兼容

4、遍历模块需要知道起止行号,支持配置,有无内容判断模块、无内容特殊处理

所以就有了下图的结构设计:

重点说一下转换、落库功能,解析落库的数据会在管理后台展示,而且为了简化非String 类型、空数据的落库处理,所以复用了 Dao 和 Dto 的能力,但带来的问题就是扩展性差。

前面也说过今后再接新的三方支付渠道可能性不大,方案设计就仅局限于当前需求(其实也没办法向后兼容,接不接新渠道、新渠道的对账单是什么样子,一切都是未知)。

然而没过多久,种种原因,导致软件界的墨菲定律发生了,解析新渠道对账单的需求就砸过来了,而且还是接连不断的砸过来!

然后上面的对比表格就变成了下面这个样子:

这里强烈吐槽一下易宝,对账单五花八门,恶心至极!

在 农行、开联通接入时,转换、落库这两部分的扩展就显得很 low 了,拷贝复制一套 Dto、Dao,但鉴于排期和回归测试的工作量,就没有改动。

到易宝接入时,由于原有的解析引擎不支持 .xlsx 文件的解析,必须要大改了,借此机会动个大手术,使其更易扩展。

结构设计也变成了下面的样子:

红框的位置是主要下刀点。

excel 解析没啥可说的,我重点说一下转换、落库这两部分的改动。

之前 某类对账单、Dto、Dao、表 这四者是 1:1:1:1 的关系,想要做到零开发的扩展性,必须打破这个关系,变成 n:1:1:n,对账单和表只能是1:1,同类型的对账单数据必须放在一张表内,便于后续数据使用。

但干掉 Dto、Dao 后,对账单内容各不相同,如何设计一个通用的 java 类来承载不同对账单的数据呢?

总不能定义一个 Dto,包含属性 field1......field100(100个应该够用了)吧,况且哪个属性对应的类型是什么也是未知的,更不能都定义成 String 类型吧。(如果单纯解析文件,可以直接按列序号用数组接收内容就行,但要实现最终动态落库,就力不从心了)

一个通用的 Dao 能用这个通用的 Dto 作为入参吗?

插入哪些字段、哪个字段是什么类型的值、插入到哪张表,Dao 怎么控制?

想到这些,差点想放弃这个方案,首先能不能实现先放一边、关键是排期允不允许,开发和回归的工作量都不小。

但如果能实现肯定会很有成就感,毕竟程序员仅存的快乐就在攻克这些难题之上了。

先说干掉 Dto 的方案,通过各种查阅资料,发现 cglib 动态生成对象的能力很适合我这个场景,也就是 net.sf.cglib.beans.BeanGenerator,它可以根据你提供的 属性名、属性类型动态创建一个 object。

而属性名、数据类型,可以从待落库的表信息中得到(查询、解析表结构),哪类对账单落到哪张表也可以通过对账中心的配置模块动态拿到。

这样就可以动态的获得一个和对账单适配的 java 对象,随后就可以把每行的内容解析出来放到这个对象中,一行对应一个对象,第一个对象创建出来后,该文件剩余行所需要的对象克隆出来就行,既简单又高效。

拿到这些承载着数据的对象后,就得想办法存到数据库了,传统的 mybatis 写法肯定满足不了了,只能另辟蹊径。干脆就自己动态的拼装 SQL,字段和内容的顺序、数据类型都能保证,CommonDao 提供一个和数据库交互的能力就行。

有了这些能力的加持后,再有新的渠道接进来,只要文件内容不是很另类,只需要建好一张表、简单配置就行。

即便这次的 XX付,格式这么奇葩,只需要修改某个小模块 [行内容解析模块],就能快速适配。

这是不是就是大家常说的发现变化、封装变化,各维度变化互不影响。

扯两句

好的系统不是一次设计出来的,而是一点点演变出来的

能够精准的发现变化并封装变化,就是好的设计

原创不易,如有收获,一键三连,感谢支持!

一款好用、易扩展的文件解析引擎,是怎么演变而来的相关推荐

  1. TPT-.net工作流是一款功能强大易扩展的工作流框架

    TPT-.net工作流 前端使用vue+elementUI开发. demo地址:https://demo.tptclub.top 表单组件可拖拽,可自定义.满足各类型字段. 清晰明了的流程设计,支持审 ...

  2. PostgreSQL数据库扩展包——原理CreateExtension扩展控制文件解析

    createExtension函数 首先看createExtension函数,该函数首先调用check_valid_extension_name函数在任何访问文件系统之前检测extension的名字的 ...

  3. 小程序子组件向父组件传值_一套组件化、可复用、易扩展的微信小程序 UI 组件库...

    如何使用 Wux Weapp 是一套组件化.可复用.易扩展的微信小程序 UI 组件库.在开始使用之前,需要先阅读微信小程序自定义组件的相关文档. 通过 npm 安装,需要依赖小程序基础库 2.2.1 ...

  4. 媒体报道 | 创业邦:巴别鸟,一款便捷好用的企业级文件协同网盘

    巴别鸟是一款文件协同网盘,致力于打造一个便捷好用的企业级应用.既能帮企业管理信息资产.存储企业文件,又能让企业内外部成员基于文件内容直接讨论的高效好用的Saas服务平台. 问:你所创业的领域,目前现状 ...

  5. Reliable, Scalable, and Maintainable Applications 高可靠、易扩展、易运维应用

    寻找翻译本书后续章节合作者  微信:18600166191 ---------------------------------- PART I Foundations of Data Systems ...

  6. 使用Amazon CDK部署基于Amazon Fargate的高可用、易扩展的Airflow集群

    前言 Apache Airflow(以下简称为Airflow) 是一项由Airbnb在 2014 年推出的开源项目,其目的是为了管理日益复杂的数据管理工具.脚本和分析工具,提供一个构建批处理工作流的方 ...

  7. Pytest自动化框架-权威教程05-Pytest fixtures:清晰 模块化 易扩展

    Fixture函数:清晰 模块化 易扩展 2.0/2.3/2.4版本新函数 text Fixture函数的目的是为测试的重复执行提供一个可靠的固定基线.Fixture函数比经典的xUnit setUp ...

  8. CodeGen融合核心扩展定制文件

    CodeGen融合核心扩展定制文件 融合核心定制文件 Harmony核心环境的各个方面都可以通过创建一个定制文件来定制,该文件是一个名为Harm的JSON文件onyCoreCustomization. ...

  9. 给Oracle表空间Tablespace扩展库文件

    版权声明:欢迎评论和转载,转载请注明来源. https://blog.csdn.net/zy332719794/article/details/78496233 一般来讲Oracle的表空间单个库文件 ...

  10. 用Nginx如何配置运行无扩展名PHP文件或非.PHP扩展名文件

    用Nginx如何配置运行无扩展名PHP文件或非.PHP扩展名文件 使用Apache + PHP 很容易做到运行无扩展名的PHP文件. 在Nginx中能做到吗?是可以的. 只需将nginx.conf文件 ...

最新文章

  1. 调用max函数求两个数中较大值
  2. 分布式离线计算—MapReduce—为什么被淘汰了?
  3. Swoole 源码分析——内存模块之内存池
  4. .net 启动mysql数据库连接_[ASP.net教程]mysql数据库连接方式(.net)
  5. Apache RocketMQ 发布 v4.4.0,新添权限控制和消息轨迹特性
  6. 机器学习、数据挖掘、计算机视觉等领域经典书籍推荐
  7. 浙江省单考单招计算机提前招,2018浙江省各校高职提前招生简章汇总及深度解析...
  8. caffe face 实现人脸相似度识别 c++版本
  9. BugKu 旋转跳跃(mp3stego(mp3隐写工具)的使用)
  10. linux命令行里输入nyancat,好玩的Linux命令行,与彩虹猫Nyan Cat一起休息下
  11. 计算机上桌面不见了怎么找回,电脑桌面上的文件消失了怎么办,如何找回
  12. 如何进行EMC Symmetrix (DMX或者VMAX)的系统健康检查
  13. Datawhale组队学习周报(第044周)
  14. 骑行318、 2016.7.15
  15. 看不到同一个网络下的其他计算机,看不到局域网其他计算机怎么办
  16. 你都有哪些面试时被虐的经历?
  17. jquery实现图片上传预览
  18. 基于Android Tiny4412平台---敦泰I2C接口FT5X06电容屏驱动原理及软件架构分析
  19. 离群值(异常值)处理
  20. python字典求平均值_Python

热门文章

  1. unexpectedly exited. Status code was
  2. 当BIM遇上GIS-无人机倾斜摄影三维建模(ContextCapture) 建设智慧城市方法详解
  3. 分库分表中间件Sharding-JDBC详解
  4. windows cmd批处理终端 快速编辑模式
  5. 单核工作法图解:事多到事少,拖延变高效
  6. 域名ip查询步骤与域名如何解析到ip
  7. 如何在电脑端同时登录多个企业微信或微信
  8. 洛谷-UVA12676 Inverting Huffman(反转树)
  9. 幼儿园数学目标_幼儿园数学区目标
  10. 菜鸟历程1腾讯云服务器 10元学生套餐购买