本篇是企业服务架构演进系列的第六篇,本篇我打算从另外一个角度去说一下企业服务架构演进的过程中我个人的一些积累。我从正式工作的第二年开始有造轮子的想法,然后从最简单最基础的方式去做,慢慢的可以做一些复杂的工具去提高开发效率,提高程序性能等。到19年我几乎每个季度都会寻找一个合适的场景用业余时间去做一些创新性的东西,这些创新虽然不是那么重要,但是对于企业发展来说,这样的方式正是企业竞争力的一种体现。

工具类

  1. DAOUtils工具类
    我从16年底开始做电子合同系统,有些列表页面需要开发,比较特别的地方是这些列表页的显示查询条件慢慢增加到20+个,而整张表的字段大概40多个。在当时这个系统还没有集成spring,orm框架也是公司自研的DAO框架,支持直接写sql执行,代码里动态拼sql。于是整个daoimpl的查询sql都是下面这样的:
if(a!= null){sql.append(a)}
if(b!= null){sql.append(b)}
if(c!= 0){sql.append(c)}

这样的if语句大概有10+条,如果每个查询条件不加注释则几乎看不懂sql是怎么拼的,拼的什么字段。
另外一个问题就是我们的表里基本上都有create_time,create_user,update_time,update_user这样的字段,每个表几乎都有修改状态等更新操作,要更新操作人等。
因此我琢磨了下,自己写了一个DAOUtils工具类。上面第一个问题的解决方案如下:
在DAOUtils实现类中增加一个@ColName(name),这个注解用在dto上面,准确的说这个dto是querydto,根据业务列表的查询模型来定的,查询dto可以直接作为DAO接口中的参数传进去,name属性值就是查询表的查询字段。在执行sql之前先通过DAOUtils里面的方法动态生成where 后面的查询条件子句,然后再拼接上select from tableName作为最终的sql。实现原理就是自定义注解+反射,后期基于这种场景我也做了一些升级。第一次升级是因为有同事反馈说这种动态拼的sql是存在sql注入的,不推荐使用。于是我提供了一个新的重载方法,返回一个Map,两个k-v,一个是返回拼的sql,一个是返回对应的paramsList。第二次升级是因为在招聘系统中有些列表页的查询涉及到了多表查询,因此在查询dto上面基于单表的动态生成显然不满足,因此重构了一版,只要在注解上声明表的别名.字段名就行,使用方式跟原来一样。
对于上面提到的第二个问题就比较简单了,抽象了一个生成update 的语句,比如update tableName set status=0,update_user=1,update_time=now() where id=?。因此在后期的权限系统中经常有这种操作。那么在写daoimpl实现类中就不用显示的声明这样的sql了,传入几个参数返回sql,调用DAO框架提供DAOOperator.updateBySql()就可以了。
目前这个工具类已经在多个工程中应用,极大的解决了一些重复代码和稳定性问题。

  1. EnumsUtils工具类
    痛点:这个工具类是为了解决当时招聘系统和corehr系统中存在的大量枚举(30+)而针对性的实现的一种统一的解决方案。招聘系统和corehr系统中的一些配置类的数据有些放到了公共数据配置平台里面以k-v的形式存储,有些就放在了代码里面,由于工程模块众多,很多枚举两个系统都要共用,一方面存在代码重复,另一方面对业务升级,前后端关于枚举数据的交互都复杂很多。
    实现原理:java类加载和反射。通过指定要扫描的枚举包扫描枚举类,然后通过反射读取枚举中的属性值信息,并以Map<String,Map<String,String>>作为方法的返回值。
    使用说明:该工具类有两个方法,用来解决从key到value的映射和value到key的映射。举个例子,比如我有员工类型枚举(StaffTypeEnum)0:正式员工,1:外包员工,2:顾问 这些数据。传入当前工程的包名,工具类自动扫描到这个枚举类,读取数据返回Map<String,Map<String,String>>格式的数据。从key到value的查找就是首先通过StaffTypeEnum类名去Map<String,Map<String,String>>找到这个枚举的子map,比如我想知道1代表什么类型的员工,直接从map中取就行了。相应的,从value到key也是同样的过程,只不过要调用另外一个方法。那么如果枚举中有多个属性数据呢,比如id,code,codeName这种三元组作为一个枚举元素的话,使用上面的方法怎么解决呢?其实在获取这个枚举元素的话方法里已经判断了枚举元素的个数,如果大于2个的话,那么默认第一个值是key,比如id是key,code和codeName就是value了,相反的,从value-key的映射也是以codeName作为key,id,code是value。多个属性值通过-符号拼接,业务代码自己处理需要的属性。不过这种枚举中存在多个值的情况比较少,一般都是k-v结构,或者单纯只有value.
  2. 报表工具类
    这里的报表工具类之前也做过一些,在一开始的物料管理系统中做过实践,当时我的项目组长使用了另外一个工具类基于JXL开发的。只是当时jxl有些限制,数据超过65535条之后就写不了了,也不支持高版本的excel.因此后期统一使用POI了。再后来基于easyexcel组件在corehr系统中解决了报表导入的问题。

maven插件&代码生成器

痛点:企业服务系统大量立项开发,众多项目开发需要手写大量entity,dto。光写这些基本半天时间过去了。
解决方案:当时想的一个解决方案就是基于maven插件去做,程序自动读取db.properties配置读取测试环境中的表数据,然后去动态生成。
实现:实际上实现是有点曲折的,由于maven本身版本的问题,导致插件在某些版本是无法运行的,另外一方面这种代码生成器实际上不应该放在pom.xml中被项目引用。因此后期又重新改版了一下。基于java jar+命令的方式实现。自定义xml配置,先读xml中的自定义配置,比如包,类的前后缀等。然后再初始化db链接。当时做了两个版本一个版本是基于公司DAO框架的,另外一个版本是基于JDBCUtils工具类的,向开源靠近。这个工具经过3次迭代才感觉让人满意,然后效果也不错。后期也跟架构部提供的这种代码生成工具做了一些对比,总体来说各有优势。虽然最后应用的次数不多,但是也成长许多。这个工具后来催生了部门领导和同事想搭建一个整体的代码生成器服务的想法,并正式立项开发了。我也合并了一些自己的代码~~。

orm框架daoclient

背景:写这个daoclient组件实际上是兴趣使然,当时花了一些时间看了公司的DAO框架,不同于mybatis和Hibernate,这有点新奇。简单点来说就是比较高级的JDBCUtils,加入了entity注解解析,结果集映射和编程式事务。
实现方案:基于java注解+反射实现,实现的过程中对java中的大多数数据类型做了处理,同时实现了相对简单的jdbc链接池。
git地址:https://gitee.com/codergit.com/daoclient

写文档生成器+接口自动化测试服务

背景:文档生成器其实很早就想动手去写了,主要是前后端分离和项目代码人员流动之后很多代码变得不容易懂了,业务文档也不多。另外一方面就是项目也比较多,有个统一的文档生成器和管理工具会更有效率。当时第一版本已经实现了扫描源码获取代码中的文档api信息了,后期由于项目时间紧张同时部门领导也不太支持这么干,有其他前端团队在搞,因此这个开发到了一半就停滞了。前端团队提供的接口api管理工具也比较原始各种手动输入,也没有自动化测试,被部门里很多开发同事吐槽,大概过了一年多后,我又重新设计了一版,将文档生成器和接口自动化测试整合到一起形成从开发到测试到文档维护等的整体功能闭环。
实现过程:在考虑实现的时候也考虑了下面三种方案1.maven插件2.java jar 3.直接读打包的class jar和源码Jar。经过各方面的考量决定使用第三种方式。于是在项目不是很忙的时候我又找回了第一版的代码,重新基于公司的RPC框架和WEB框架做了一些调研,在开始立项之前先咨询了各个技术部门的老大以及多位自身测试开发大佬。虽然有些负面反馈,但是我觉得还是可以尝试搞一搞的。
实现原理
1.通过Maven编译插件打出class包,然后上传到文档生成器界面中,由程序自动通过类加载和反射的机制获取接口的接口包名,接口名,参数和返回类型等元数据,存储到数据库中。
2.通过maven 源码包插件打出源码包,然后上传到文档生成器界面上,由程序自动解析代码中的注释,存入数据库中。
3.将上述解析到的数据通过界面展示,然后录入对应的参数发起接口测试调用。
最终结果:项目的核心代码基本完成,多个服务的文档注释,元数据等都已存入数据库中。

fastjson升级工具

痛点:我所在的部门有众多工程服务,大量引用了fastjson jar包,由于fastjson从19年开始暴露出多个版本的严重bug导致部门内工程服务升级困难,升级时间延长。因此想通过一种方式去解决多个工程引入fastjson pom的问题,将低版本fastjson升级到高版本。
实现方案:调研java 通过jgit连接到远程git库,然后扫描本地项目的工作目录,将pom.xml读取出来,显示替换fastjson 为高版本,然后自动提交到远程仓库。
最终成果:我多次负责了部门内fastjson的升级工作,因此这个升级工具也跟着升级了2次。但是最终的使用效果却不太好。手动狗头~~

轻量级监控平台

痛点:我在企业信息部门的中后期做了一些系统调优的工作,发现在监控方面公司做的还不太够,虽然有了比较全的监控和报警。但是针对测试环境,针对线上环境的特定维度都还有些欠缺,也跟负责监控的同学聊了一下,另外跟运维的同事沟通了自己的想法。决定基于shell做一些轻量级监控的脚本和数据收集工作。
实现方案:基于Linux shell脚本实现机器ip,机器负载,机器内存磁盘,java服务,进程,线程,gc等信息的收集和上报,使用一个全局shell做脚本下发和脚本更新的工作。收集上报之后通过服务端的定时任务去扫数据结合钉钉机器人做报警。
最终成果:产出多个针对性的监控脚本,在测试环境中多次准确报警fgc,磁盘占满等情况,基于公司框架和springboot做了两套。虽然不够生产级的水准,但是可作为入门监控的一种选择。
说明:git地址中的代码没有监控脚本,为了安全考虑将涉及公司信息和公司代码的地方做了简化处理。相应的脚本已经在之前的博客中发布了,可以做对应的看。
git地址:https://gitee.com/codergit.com/lightmonitor

aop集成工具组件

痛点:我们部门负责的多个服务,在维护的过程中出现了一些排查困难,性能优化效率比较低,线上动态sql不知道怎么拼的问题。另外一方面接口参数调用校验也存在一些硬编码问题。
实现方案:1.集成公司架构部的DAO组件,RPC框架,Spring AOP,使用aop的多种通知方式结合自定义注解做方法执行拦截,声明式事务的提交回滚,sql打印等功能。

  • 声明事务
  • 编程事务
  • 日志打印
  • 参数校验
  • 接口执行时间
  • 内部方法执行时间
  • sql打印
    最终效果:组件整体实现了2个版本,同时在3个项目中实践,后期也规划了一些整合redis等功能的需求。
    git地址:https://gitee.com/codergit.com/aop-scale

数据库表结构规范设计检测工具

痛点:这个工具源于一次关于数据库表设计的坑,当时要做动态报表的导出,报表涉及8张表,150+字段,任意选字段,任意导数据。在进行动态报表导出的时候需要对一些配置类的,枚举类的数据做一些变换,比如staffid换姓名,xxType换xxName这种的,因此实现之前需要对8张表的所有字段全部摸清分类,但是由于表字段和注释等不规范,整体方案落地过程中经常掉坑里。
实现方案:基于mysql的数据库表和字段的元数据做分析,并将不符合设计规范的地方收集起来,然后通过easyexcel或者输出控制台的方式去展现这些问题。
最终效果:整体功能基本完成,结合阿里巴巴java开发手册-数据库设计章节和公司数据库设计规范文档做基础,完成了多个场景的检测。目前通过开源框架重新实现了一个版本,已开源。
git地址:https://gitee.com/codergit.com/dbmodelcheck

高性能数据导出服务

背景:这个导出服务源于一次和同事的讨论,有个财务单据的导出需求,说要导出10万单据,貌似字段挺多的样子,意思是实现起来可能会有性能问题,先把需求怼回到产品吧。我这边想着能否写个工具去并行导出,提高导出性能。于是就自己捣鼓去了
实现方案:基于公司框架和java 8的并行api做异步导出和数据转换,另外整合easyexcel做报表的生成。
最终效果:整体功能基本完成,经过多轮测试30万数据最快5秒导出完成,虽然没有最终用到项目中,但是这确实是一个解决报表导出比较好方案。目前通过开源框架重新实现了一个版本,已开源。
git地址:https://gitee.com/codergit.com/commonreport

整体来说我可能并不是那么安分的去做分内之事,也不想在公司里真正的去摸鱼,总要追求一些东西,不断扩展自己的边界和能力。上面的工具,服务等虽然有些成功的应用到了企业系统中,有些失败了,甚至根本没有被实战过,但是至少我去尝试了,也算一种成长吧。对于上面的工具如果有你认可的,欢迎给个star哈。后续会另外创建系列文章讲述基于分布式微服务的租房架构设计实践,欢迎关注。

我最近整了一个公众号,持续输出原创内容,敬请关注:

架构设计@工程设计@服务稳定性之路

企业服务架构演进-走上造轮子之路相关推荐

  1. 企业服务架构演进-第三方系统与自研之道

    本篇是企业服务架构演进系列的第五篇,本篇主要讨论的内容是在进行企业信息系统建设的过程中我们如何针对当前业务背景,部门需求选择合适的企业信息系统.是招人搭建企业信息部门建设还是购买第三方软件服务,或者基 ...

  2. 企业级BPM之微服务架构演进

    BPM平台在各行业的IT架构中都是重要的基础支撑平台,十二五期间,企业级BPM作为SOA体系下的关键组件,经历了一个加速建设的过程.我们也有幸参与了一些行业的流程平台建设,今天与大家分享我们在流程引擎 ...

  3. GitChat · 架构 | 为什么微服务实施那么难?如何高效推进微服务架构演进

    GitChat 作者:顾宇 原文:为什么微服务实施那么难?如何高效推进微服务架构演进 关注公众号:GitChat 技术杂谈,一本正经的讲技术 前言 笔者从 2013 年加入 ThoughtWorks ...

  4. 为什么微服务实施那么难?如何高效推进微服务架构演进

    为什么微服务实施那么难?如何高效推进微服务架构演进 前言 笔者从 2013 年加入 ThoughtWorks 至今共 4年时间.在这 4 年的时间里,我分别以 开发人员, DevOps 工程师.Dev ...

  5. 大图书馆 #7 互联网企业服务架构书单

    春节在家整理存书,发现了当时在拼多多做业务开发工作的时候,用来帮助理解互联网企业服务架构的若干书籍.这些书里的技术方案可能有一定的落后,但是对于帮助新入职场的互联网公司程序员,了解一个典型的互联网企业 ...

  6. 基于企业服务架构的新一代企业管理应用软件

    基于企业服务架构的新一代企业管理应用软件 --在2007年中国开发者精英论坛上的演讲 IT168耿英英: 企业发展离不开信息化,而信息化的关键是企业管理的信息化,新一代的企业管理软件,使得现代的企业可 ...

  7. 支付宝小程序Serverless服务架构演进 | mPaaS 线下沙龙 CodeDay#1 分享实录

    文章概要: 随着云计算的深入,Serverless 这种全新的架构模式正在受到越来越多人的关注.通过 Serverless,开发者可以从繁杂的底层基础实施中解放出来,专心聚焦于业务实现,快速铺开业务. ...

  8. 支付宝小程序 Serverless 服务架构演进 | mPaaS 线下沙龙 CodeDay#1 分享实录

    文章概要: 随着云计算的深入,Serverless 这种全新的架构模式正在受到越来越多人的关注.通过 Serverless,开发者可以从繁杂的底层基础实施中解放出来,专心聚焦于业务实现,快速铺开业务. ...

  9. 软件架构--服务架构演进

    软件架构--服务架构演进 1 介绍 2 各架构介绍 单体应用架构 MVC (Modle View Controller) 架构 RPC (Remote Procedure Call)架构 SOA (S ...

最新文章

  1. apache2.4中layout模块和ssi模块的冲突
  2. 编写一个程序,实现将存放在AX和DX中的32位数据循环右移二进制数的4位。(DX存放高字节内容,AX存放低字节内容)
  3. mongodb 怎样检测 安装成功 以及mongodb的一些增删改查命令
  4. 商汤3DAR团队-3D视觉组招聘
  5. OpenCV4.0-alpha发布!新增多个深度学习特性
  6. Oracle系列:(22)视图
  7. 四、docker-compose的编程模版
  8. Web笔记:jQuery的使用
  9. nginx集群,带负载均衡(监听多个端口),超详细,轮询分发
  10. 推荐几个优秀的微信小程序UI组件库
  11. 请问手机有没有简单好用图片去水印app?这4款手机软件可以实现去水印
  12. 关于计算机的想象类作文,想象类作文范文
  13. 数据库学习总结(六)——查询练习题(1)
  14. 用Java判断ab大小_比例类数据的差异性检验与AB测试的终止点
  15. win10 文件夹设置区分大小写
  16. 天视通摄像头设置教程_天视通摄像头设置教程_直播教程 | 使用虎牙伴侣背景消除,来点新鲜的直播玩法!......
  17. Java 面向对象(六)
  18. 160个crackme 持续更新(1\2\3\4\6\8\9)
  19. c语言齿轮标准模数选择编程,齿轮模数选取及相关国家标准
  20. 在Linux内核接收路径查找top 1的IP地址

热门文章

  1. caffe自定义层:imagedata层实现多标签
  2. 计算机专业有哪些专业课比较难,计算机专业课程有哪些 学计算机难不难
  3. 骨传导耳机哪个品牌比较好?骨传导耳机推荐
  4. PostgreSQL安全基线
  5. Maltego的使用教程
  6. 20220305-ES6
  7. 【凯子哥带你做高仿】“煎蛋”Android版的高仿及优化(三)——使用GreenDao实现本地Sqlite缓存
  8. MYCCL特征码定位器详细使用之内存定位
  9. Python函数默认参数为空列表
  10. 学习iOS 编程的一些建议