需求背景
前几天有个任务,须要在系统中导入几个excel文件,excel字段比较多(最少也有70来个字段,多的有170个字段),要的比较急,分给3个同事开始作。几个同事憨憨的就开始根据excel文件建立表了(你们约定好,excel的b列字段对应db字段col_b,c字段对应col_c),而后实现导入导出功能了。忙的满头大汗,终于在下午弄出来了,此处应该有掌声^_^java
需求痛点
悲剧发生了,需求变动了,原先的表有的废弃了,有的字段变动了,还有新表来了,明天交付。一下哀嚎遍地,成妾作不到啊。。。算法
架构设计
那么这个需求怎么才能实现快速交付呢?咱们分析下 有哪些体力活:spring
- 因为字段较多,建表sql,就算1个字段20s,中间一个不出错20*170/60=56.7min 2.因为使用easyExcel导入导出,相应的@ExcelProperty不少 3.需求不肯定,字段和表的常常变更 4.后台逻辑雷同,导入都是先删除再插入 解决思路:
- 几分钟写个小程 序读取excel,获取表头信息生成对应建表sql,须要花点时间写个数字转换成excel字母列的小算法
- 根据db的表结构生成对应文件,我是改造mybatis-generate来生成含有@ExcelProperty的bean 3.实现了1和2,天然不怕字段变更了,花几分钟时间从新生成下就ok了 4.代码层面的优化下面再来具体分析
代码层面的架构
解决了最大的体力劳动,代码上面大量的重复仍是很不爽,改造前controller代码相似:sql
try{ XXSer.importXXX }catch(Excepotion){ //错误信息处理 }catch(Excepotion1){ //错误信息处理 } return....
使用spring的统一异常处理,controller里面只须要调用service的业务逻辑方法便可 改造前service代码相似:mybatis
if(aaa==null){ throw new BizException("不能。。。") } 读取excel文件 删除原先记录 插入原先记录 插入日志
观察发现,各个service的逻辑能够说是同样的,基本上就是表名不同,这种体力活怎么优化呢? spring提供的aop就是个很好的实现,能够定义一个方法或者自定义注解,而后经过aop拦截实现相应功能。若是没有使用spring,直接经过动态代理也能够实现相似功能。无论用什么方式实现,思想都是抽取公用逻辑,不须要满篇ctrl+c,ctrl+v架构
后期优化
若是相似需求不少,能够考虑作成1个功能,页面导入1个excel文件,系统生成对应文件,复制到相应位置。甚至能够更近一步,所有动态代理,反射生成对应代理类,经过传入tablename和具体字段复用一个公用sql,新增一个表都无需重启系统。性能
总结
- 用代码来替代体力劳动
- 观察找出公用逻辑,透过现象看本质,尽可能复用公用部分。
本文只是拿了一个需求场景来描述架构的思路,实际中会有不一样的需求,例如每一个表有对应的业务逻辑,报表导入,查询有较高的性能要求等等,不能生搬硬套。优化