当我们的
Service方法需要在"执行前 / 执行中 / 执行后 / 执行失败"四个节点预埋入口,让后续业务方能"只重写对应方法就实现新需求"时,该怎么设计?
这是一道非常典型的"对扩展开放、对修改封闭"(OCP)诉求题。在 Spring + MyBatis-Plus 的项目里,由于 ServiceImpl 的单继承约束,可选的方案并不多。本文给出一份可直接落地的方案 A(模板方法 + ServiceImpl 继承),以及完整的最佳实践清单。
当我们的
Service方法需要在"执行前 / 执行中 / 执行后 / 执行失败"四个节点预埋入口,让后续业务方能"只重写对应方法就实现新需求"时,该怎么设计?
这是一道非常典型的"对扩展开放、对修改封闭"(OCP)诉求题。在 Spring + MyBatis-Plus 的项目里,由于 ServiceImpl 的单继承约束,可选的方案并不多。本文给出一份可直接落地的方案 A(模板方法 + ServiceImpl 继承),以及完整的最佳实践清单。
概述
项目采用 生产者-消费者 架构实现日志的异步持久化。admin 模块负责生产日志消息并发送到 Kafka,async 模块负责消费 Kafka 消息并双写 MySQL 和 Elasticsearch,实现业务请求与日志落库的解耦。
生产者端 (admin 模块):
HTTP 请求
├── ApiLoggerFilter (OncePerRequestFilter)
│ └── ApiLoggerService.sendApiLogToDBMQ/ESMQ
│ └── @Async("loggerTaskExecutor")
│ └── KafkaTemplate.send()
└── Controller (标注 @ApiOperationLog 的方法)
└── ApiOperationLogAspect (AOP 环绕通知)
└── OperationLoggerService.sendOperationLogToDBMQ/ESMQ
└── @Async("loggerTaskExecutor")
└── KafkaTemplate.send()
如果需要固定IP,则需要确定需要修改的网卡名称,下面以固定IP成192.168.1.23为例。
执行以下命令查看网卡信息:
ifconfig
每个有经验的开发者都有自己程序的开发规范,这篇文章是根据个人经验,以SpringBoot框架,java开发语言为示例,归纳总结出的一种代码目录结构。
在开发实践中不一定完全适合所有人,但是对于大部分人来说,应该可以满足大部分的场景。同时在实践中,需要基于需求,进行相应的调整,但大体上建议遵循该目录结构,提高代码的可读性以及可维护性.
即使是单体应用程序,也建议按照模块进行划分,每个模块对应一个目录,目录下存放该模块的代码。
framework:框架模块,为整个应用程序提供基础功能,例如:数据库连接、缓存连接、日志记录、异常处理等。框架模块下应当有以下目录:
common:通用模块,为整个应用程序提供通用功能,例如:文件上传、图片处理、数据验证等,同时实体类、枚举类、工具类也可以放在该模块下。common模块下应当有以下目录:
业务模块:为业务功能提供支持,例如:后台管理、用户管理、权限管理、订单管理等。每个模块下应当有以下目录:
注意:如果业务模块中需要自定义特有的拦截器或者过滤器等需求,可以在对应的模块下创建相应的目录,例如:interceptors、filters、aspects等。
async:异步任务模块(可选),为应用程序提供异步任务功能,例如:定时任务、邮件发送、短信发送等。异步任务模块下应当有以下目录:
此次系统部署在exsi 7虚拟化平台中,并且使用的是虚拟磁盘进行扩容。
首先需要在exsi平台中增加系统的硬盘空间,根据以下步骤进行操作:


当我们在查看一些公司中小系统产品的源码时,我们会发现系统实体VO总会有一些固定出现的字段,例如:code、createBy、updateBy......,里面存放的是一些唯一标识,例如:id或者unCode的值。其中createBy、updateBy这两个字段我们在接口返回业务数据时,需要将这些唯一标识通过“翻译”的手段将其变成用户能够看得懂的数据,以便前端展示在页面,例如:username、name等,本案例就是通过介绍一个VO字段翻译抽象类的实现方案来为新手读者扩宽设计思路。
本方案最佳实践中需要要求有以下前提,如果是改造系统,也需要根据以下前提来对系统进行完善和改造:
执行如下命令即可。
sudo rpm -Uvh http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.18.0-2.el7.ngx.x86_64.rpm
若出现其他问题,可按照提示进行安装依赖,正常来说直接运行即可。
如果不想要该发行版本,则可以到http://nginx.org/packages/centos/7/x86_64/RPMS/中进行选择。
该设计使用回调接口的设计思路进行实现,拥有灵活且符合封闭原则的特点,示例的源码中添加了传参的示例,分为两种:
通过构造函数传参:
该种方式适用于在主进程或者new回调方法具体实现类的场景下使用,可以用于传输一些在具体实现类中获取不到的参数,亦或者是一些回调方法不同逻辑都通用的参数,例如:当前登录信息的上下文、mapper实例等。
通过回调方法进行传参:
这种方式适用于在存在异步操作逻辑中传输异步操作结果,用于在回调方法中针对不同的结果执行不同的业务逻辑,同时需要注意对参数进行校验。