切面Aspect + 策略模式实现待办提醒功能

1.背景

产品需要实现一个待办提醒功能,就是核心业务发生变更即提醒业务员去处理相关业务。譬如:订单上传了支付凭证,那么就会提醒相关业务员去待办列表操办。

2.表设计

其实表设计主要是两张表sys_todo、sys_todo_detail

一张是待办核心表,主要是记录待办类型,待办业务id等。

CREATE TABLE `sys_todo` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',`model` int NOT NULL DEFAULT '0' COMMENT '归属模块: 0-crm 1-srm',`type` int NOT NULL DEFAULT '0' COMMENT '待办类型',`biz_id` bigint NOT NULL DEFAULT '0' COMMENT '业务id',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='待办统计表';

另一张是待办详情表,主要是记录这个待办能做哪些操作。

CREATE TABLE `sys_todo_detail` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',`todo_id` bigint NOT NULL DEFAULT '0' COMMENT 'sys_todo表id',`title` varchar(50) NOT NULL DEFAULT '' COMMENT '标题',`url` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '地址',`is_pop` int NOT NULL DEFAULT '0' COMMENT '是否弹窗 0-否 1-是',`content` varchar(3000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '内容',`sort_num` int NOT NULL DEFAULT '0' COMMENT '排序',PRIMARY KEY (`id`),KEY `idx_todo_id` (`todo_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='待办统计详情表';

举例:sys_todo 有个待办类型是【上传支付凭证】,id=1,sys_todo_detail 待办详情表,就有todo_id 为1的内容,譬如【查看】、【审核】操作的两条记录。

当然,这些表具体实现得根据具体业务设计来实现。

3.如何实现

3.1 业务埋点

业务埋点,也就是在每一个相关业务代码里面,加上待办的埋点,让相关待办业务内容插入待办表。譬如:【上传支付凭证】,就得在上传支付凭证的代码最后上传成功的地方,写上上传待办的业务代码。

3.2 切面Aspect + 策略模式

3.2.1 先定义好切面

这里我在项目里面,定义好切面类。

@Component
@Aspect
public class SrmTodoAspect {//这里拦截mybatis-plus底层方法@Pointcut("(execution(* com.baomidou.mybatisplus.extension.service.IService.update*(..))" +"||execution(* com.baomidou.mybatisplus.extension.service.IService.save*(..))" +"||execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.update*(..))" +"||execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.insert(..)))" )public void todo(){};//策略A@Resourceprivate ATodoStrategy aTodoStrategy;//策略B@Resourceprivate BTodoStrategy bTodoStrategy;//线程池@Resourceprivate TaskExecutor taskExecutor;@Around("todo()")public Object around(ProceedingJoinPoint point) throws Throwable {Object[] args = point.getArgs();Object obj = point.proceed();Object arg = args[0];List<Object> paramList = null;if(Objects.isNull(arg)){return obj;}if(arg instanceof ArrayList){paramList = (List)arg;}else {paramList = Arrays.asList(args);}if (CollectionUtil.isEmpty(paramList)){return obj;}/**  这里用到捕获异常很关键,不能因待办出现异常而影响主流程,*  用线程池避免待办处理过慢影响主流程性能*/taskExecutor.execute(()->{try{Thread.sleep(1000L);dealTodoStrategy(paramList);}catch (Exception e){}});return obj;}/**   TodoContext 是策略模式的上下文*   aTodoStrategy、bTodoStrategy 是具体的策略*/private void dealTodoStrategy(List<Object> paramList) {TodoContext context = null;Object param = paramList.get(0);if(param instanceof A){context = new TodoContext(aTodoStrategy);}else if(param instanceof B) {context = new TodoContext(bTodoStrategy);}if(context != null){context.executeStrategy(paramList);}}}

特别说一句:这里其实最初的设计并不是用切面,而是用mybatis拦截器 Interceptor 去实现获取到insert或update后的实体的,但是拦截mybatis-plus的saveBatch方法能拿到List实体,但是没有id。因此不能很好处理待办业务。原因:大家可以去看下CSDN

3.2.2 定义策略模式

策略接口(TodoStrategy 

public interface TodoStrategy {void dealTodo(List list);
}

Context类

public class TodoContext {private TodoStrategy strategy;public TodoContext(TodoStrategy strategy){this.strategy = strategy;}public void executeStrategy(List list){strategy.dealTodo(list);}
}

策略实现类 (ATodoStrategy )

@Service
public class ATodoStrategy implements TodoStrategy {@Overridepublic void dealTodo(List list) {if(CollectionUtil.isEmpty(list)){return;}TodoForm todoForm = null;List<Enquiry> enquiryList = (List)list;List<Long> enquiryIdList =         
enquiryList.stream().map(Enquiry::getId).collect(Collectors.toList());//根据id找到数据库实体类enquiryList = enquiryService.findList(new EnquiryQuery().setIdList(enquiryIdList));//遍历实体类,然后根据不同的实体状态去实现待办规则新增或消除功能for(Enquiry enquiry : enquiryList){Long id = enquiry.getId();//新增去报价待办if(EnquiryStatusEnum.WAIT_QUOTE.getKey().equals(enquiry.getStatus())){}//消除去报价待办if(EnquiryStatusEnum.HAD_QUOTE.getKey().equals(enquiry.getStatus())){}}}
}

4.总结

待办实现方式两种:①埋点 ②切面Aspect + 策略模式

个人比较推荐② ,因为这个代码设计好处如下:

1.不需要“过分”埋点。埋点的话,容易漏埋点。譬如新增代码业务代码在插入操作后埋点了,但是突然另一个业务也有插入操作,但是忘记埋点,那么待办就容易遗漏。

2.代码集中维护,模块分层清晰。也就是待办新增或消除逻辑,统一写在策略模式里面了,只需要去策略模式里面维护即可。这样也能减少在业务代码过多埋点造成代码臃肿。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/154769.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

福州大学《嵌入式系统综合设计》实验四:边缘检测

一、实验目的 BMCV 提供了一套基于 Sophon AI 芯片优化的机器视觉库&#xff0c;通过利用芯片的 TPU 和 VPP模块&#xff0c;可以完成色彩空间转换、尺度变换、仿射变换、透射变换、线性变换、画框、JPEG 编解码、BASE64 编解码、NMS、排序、特征匹配等操作。 本实验的目的是…

C++中的内存管理

✨前言✨ &#x1f4d8; 博客主页&#xff1a;to Keep博客主页 &#x1f646;欢迎关注&#xff0c;&#x1f44d;点赞&#xff0c;&#x1f4dd;留言评论 ⏳首发时间&#xff1a;2023年11月21日 &#x1f4e8; 博主码云地址&#xff1a;博主码云地址 &#x1f4d5;参考书籍&…

基于C#实现KMP算法

一、BF 算法 如果让你写字符串的模式匹配&#xff0c;你可能会很快的写出朴素的 bf 算法&#xff0c;至少问题是解决了&#xff0c;我想大家很清楚的知道它的时间复杂度为 O&#xff08;MN&#xff09;&#xff0c;原因很简单&#xff0c;主串和模式串失配的时候&#xff0c;我…

电脑便签工具推荐哪个?电脑上好用的便签软件使用哪一款

对于职场办公人士来讲&#xff0c;一款好用的电脑便签工具可以给日常工作带来极大的便利&#xff0c;如果您的日常工作离不开电脑工具&#xff0c;您就会知晓电脑便签工具在日常工作中的重要&#xff0c;电脑便签通常以一个小的窗口呈现在电脑桌面上&#xff0c;记录一些工作中…

KVM网络环境下vlan和trunk的理解

vmware exsi 平台&#xff0c;虚拟交换机管理界面的上行链路是什么意思 VMware ESXi中的虚拟交换机管理界面中的“上行链路”&#xff08;uplinks&#xff09;是指虚拟交换机连接到物理网络的物理网络适配器。在ESXi中&#xff0c;虚拟交换机&#xff08;vSwitch&#xff09;用…

JAXB:根据Java文件生成XML schema文件

说明 JAXB有个schemagen脚本&#xff0c;可以根据Java文件生成XML schema。这个工具在JAXB独立发布包中有&#xff0c;可以从官网下载JAXB的独立发布包&#xff1a; https://eclipse-ee4j.github.io/jaxb-ri/ 示例 使用schemagen -d <path> <java files>格式 …

安装rabbitMQ

安装rabbitMQ linux安装rabbitMQ centos7下 需要先安装JDK 安装Erlang 需对应版本 安装对应版本的rabbitMQ 参考&#xff1a;CentOS7安装RabbitMQ简单实用教程_普通网友的博客-CSDN博客 启动 systemctl start rabbitmq-server出现的问题 启动失败 Job for rabbitmq-ser…

CDN加速:技术的巅峰与普及的难题

在当今数字化时代&#xff0c;快速、稳定的网络连接已成为企业成功的关键要素之一。为了应对用户需求的不断增长和全球范围内的网络拓扑结构&#xff0c;CDN&#xff08;Content Delivery Network&#xff0c;内容分发网络&#xff09;技术应运而生。尽管CDN加速在提高网站性能…

顺序表和链表

1.线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线…

最新最全系列之Selenium:传入webdriver驱动的新方法 Service()函数;以前的executable_path报警告,即将弃用

传入webdriver驱动的新方法 Service()函数&#xff1b;以前的executable_path报警告&#xff0c;即将弃用 以前的方法 举例&#xff1a;webdriver.Chrome(executable_pathdriver_path)&#xff1b;看提示警告&#xff0c;提示该方法即将被弃用&#xff1b;如下图&#xff1a; …

mysql底层是如何存放数据的

总览 首先总的来说&#xff0c;分为四个层级&#xff0c;行页区段。行就是数据库里的一行数据。 但一次从磁盘读进内存的数据量是一页&#xff08;页是读写的单位&#xff0c;默认16KB一页&#xff09;&#xff0c;页分很多种类&#xff0c;例如数据页、溢出页、undo日志页。 …

linux驱动.之 网络udp应用层测试工具demon(一)

绑定vlan&#xff0c;网卡的demon&#xff0c;如果有多个网卡&#xff0c;多个vlan&#xff0c;网卡的ip设置成一致&#xff0c;那就不能只简单绑定ip来创建socket&#xff0c; 需要绑定网卡设备 客户端udp_client.c #include <stdio.h> #include <string.h> #inc…

工业领域的设备“监测”和“检测”有何区别?

在工业领域中&#xff0c;设备的监测和检测是关键的运维活动&#xff0c;它们在保障设备可靠性和生产效率方面发挥着重要作用。尽管这两个术语经常被人们混为一谈&#xff0c;但它们在含义和应用上存在一些关键区别。 "监测"与"检测"的概念 1. 监测&#…

使用wxPython和PyMuPDF合并PDF文档并自动复制到剪贴板

导语&#xff1a;处理大量的PDF文档可能会变得复杂和耗时。但是&#xff0c;使用Python编程和一些强大的库&#xff0c;如wxPython和PyMuPDF&#xff0c;可以使这个任务变得简单而高效。本文将详细解释一个示例代码&#xff0c;展示如何使用这些库来创建一个可以选择文件夹中的…

vue3插槽的使用方法和优缺点

插槽的使用方法 在Vue 3中&#xff0c;插槽&#xff08;slots&#xff09;是一种用于传递和分发组件内容的灵活机制。插槽可以用来定义组件内部的占位符&#xff0c;然后在父组件中填充具体内容。下面是Vue 3中使用插槽的基本方法&#xff1a; 默认插槽 <!-- ChildCompon…

C#学习相关系列之Linq常用方法---排序(一)

一、构建数据 public class Student_1{public int ID { get; set; }public string Name { get; set; }public int Chinese { get; set; }public int Math { get; set; }public int English { get; set; }public override string ToString(){return string.Format("ID:{0},…

PythonAppium自动化测试环境搭建

Python环境 在CMD中运行 pip install Appium-Python-Client Microsoft Windows [版本 10.0.19045.3693] (c) Microsoft Corporation。保留所有权利。C:\Users\Administrator>pip install Appium-Python-Client Collecting Appium-Python-ClientDownloading Appium-Python-…

从零开始 通义千问大模型本地化到阿里云通义千问API调用

从零开始 通义千问大模型本地化到阿里云通义千问API调用 一、通义千问大模型介绍 何为“通义千问”&#xff1f; “通义千问大模型”是阿里云推出的一个超大规模的语言模型&#xff0c;具有强大的归纳和理解能力&#xff0c;可以处理各种自然语言处理任务&#xff0c;包括但…

springboot多环境配置

前言 在实际项目研发中&#xff0c;需要针对不同的运行环境&#xff0c;如开发环境、测试环境、生产环境等&#xff0c;每个运行环境的数据库…等配置都不相同&#xff0c;每次发布测试、更新生产都需要手动修改相关系统配置。这种方式特别麻烦&#xff0c;费时费力&#xff0…

参数传递方式

参数传递方式教材上大都说有两种&#xff0c;一种是值传递&#xff0c;另一种是指针传递。而后者本质上依然是值传递。 底层原理 对于值传递还是指针传递&#xff0c;传递的都是相应的值&#xff0c;只不过指针传递传递的是地址的副本&#xff0c;修改副本对原来数据没有任何…