当前位置: 首页 > news >正文

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

相关文章:

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

1.背景 产品需要实现一个待办提醒功能&#xff0c;就是核心业务发生变更即提醒业务员去处理相关业务。譬如&#xff1a;订单上传了支付凭证&#xff0c;那么就会提醒相关业务员去待办列表操办。 2.表设计 其实表设计主要是两张表sys_todo、sys_todo_detail 一张是待办核心表…...

SAP 调取http的x-www-form-urlencoded形式的接口

一、了解下x-www-form-urlencoded形式对于SAP来说有啥区别 简单来说&#xff0c; 1.raw格式就是标准的json格式&#xff1a;{“Name”:“John Smith”&#xff0c;“Age”: 23} 2.x-www格式是要转化一下的&#xff1a;NameJohnSmith&Age23 字段与字段相互连接要用 & 符…...

thingsboard3.6的mailConfigTemplateController错误

1、bug内容 使用3.6版本的tb代码进行打包生成boot的jar包,在启动的时候会报错mailConfigTemplateController bean初始化找不到文件路径。 Error creating bean with name mailConfigTemplateController defined in URL [jar:file:/D:/yuxinwei/AE/thingsboard/thingsboard-3…...

Go语言中获取IP

简介 在net包中提供了获取所有网卡的ip&#xff0c;一般不会用127.0.0.1,::1这样的本地回环地址&#xff0c;可以过滤掉&#xff0c;如果想要获取当前真正在使用的地址&#xff0c;得通过net.Dail去连一下才知道 获取ip地址 func main() {fmt.Println(getIpv4())fmt.Println…...

【Computer Vision Foundation】全球计算机视觉基金会论文网

计算机视觉基金会&#xff08;Computer Vision Foundation&#xff0c;简称CVF&#xff09;是一个致力于推动计算机视觉领域研究和发展的组织。以下是关于计算机视觉基金会的一些基本信息&#xff1a; 成立目的&#xff1a; CVF成立的目的是促进计算机视觉领域的学术研究、技术…...

计网(复习自用)

计算机网络 1.概述 1.1概念 含义 计算机网络&#xff1a;是一个将分散的。具有独立功能的计算机系统&#xff0c;通过通信设备和线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。 简单点说&#xff0c;计算机网络是互联的&#xff0c;自治的计算机集…...

安徽省广德市选择云轴科技ZStack Cloud云平台建设县级智慧城市

信创是数字中国建设的重要组成部分&#xff0c;也是数字经济发展的关键推动力量。作为云基础软件企业&#xff0c;云轴科技ZStack产品矩阵全面覆盖数据中心云基础设施&#xff0c;ZStack信创云首批通过可信云《一云多芯IaaS平台能力要求》先进级&#xff0c;是其中唯一兼容四种…...

【计算思维】蓝桥杯STEMA 科技素养考试真题及解析 6

1、明明买了一个扫地机器人&#xff0c;可以通过以下指令控制机器人运动: F:向前走 10 个单位长度 L:原地左转 90 度 R:原地右转 90 度 机器人初始方向向右&#xff0c;需要按顺序执行以下那条指令&#xff0c;才能打扫完下图中的道路 A、F-L-F-R-F-F-R-F-L-F B、F-R-F-L-F-F…...

nuxt3项目修改端口号

nuxt的默认端口号是3000 一、修改开发环境端口号 方式一&#xff1a;使用环境变量配置,设置&#xff08;PORT 或 NUXT_PORT&#xff09; # .env PORT3001 #http://localhost:3001/ NITRO_PORT3001 #http://localhost:3001/ 方式二&#xff1a;nuxt.config.ts里配置…...

c语言中使用openssl对rsa私钥解密

单次加密数据的最大长度&#xff08;block_len&#xff09;&#xff0c;由RSA秘钥模长RSA_size()和填充模式有关 填充模式&#xff1a;RSA_PKCS1_PADDING&#xff0c; block_lenRSA_size() - 11填充模式&#xff1a;RSA_PKCS1_OAEP_PADDING&#xff0c;block_lenRSA_size() - 4…...

mysql中数据是如何被用B+树查询到的

innoDB是按照页为单位读写的 那页中有很多行数据&#xff0c;是怎么执行查询的呢&#xff0c;首先我们肯定&#xff0c;是以单向列表形式存储的&#xff0c;提高了增删的效率&#xff0c;但是查询效率低。所以实际上对页中的行数据进行了优化&#xff0c;能以二分的方式进行查…...

Redisson 分布式锁的最佳实践

Redisson 分布式锁的最佳实践 第一、添加依赖第二、添加redisson配置类第三、添加测试类测试结果扩展知识redisson锁中lock方法和tryLock方法有什么区别锁续约 注意事项 引言 在现代分布式系统中&#xff0c;处理并发问题是至关重要的。分布式锁是解决这类问题的关键工具之一。…...

ArkTS声明式开发范式

装饰器 用来装饰类、结构体、方法以及变量&#xff0c;赋予其特殊的含义&#xff0c;如上述示例中 Entry 、 Component 、 State 都是装饰器。 Component 表示这是个自定义组件&#xff1b; Entry 则表示这是个入口组件&#xff1b; State 表示组件中的状态变量&#xff0c;…...

史诗级云故障敲响警钟,应用保障不能没有“连续键”!

近日&#xff0c;知名云服务商出现一次史诗级的云故障&#xff1a;全球所有区域/所有服务同时异常&#xff0c;故障持续长达3小时之多&#xff0c;云上众多应用受到极大影响。 如今&#xff0c;在一个充满不确定性和复杂性的数字化时代&#xff0c;哪怕是顶级云服务商亦不能避…...

SSH连接远程服务器报错:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED 解决方法

一.错误描述 报错信息里提示了路径信息/root/.ssh/known_hosts:20 二.解决方案 方法一 输入以下指令&#xff1a; ssh-keygen -R XXX&#xff08;需要连接远程服务器的ip&#xff09; 按照我的例子ip:10.165.7.136&#xff0c;会返回以下信息: 重新尝试连接&#xff1a; 输…...

数据库——查询连续的月份

一、GP或PGSQL with recursive t(n) as (select date(2023-01-01) union all select n1 from t where n < now()) select to_char(n, yyyy-mm) as ny from t group by ny order by ny 二、Hive select add_months(FROM_UNIXTIME(unix_timestamp(SUBSTR(start_date, 1, 7…...

git代码提交命令(如何提交代码)

# 提交暂存区到仓库区 $ git commit -m [message]# 提交暂存区的指定文件到仓库区 $ git commit [file1] [file2] ... -m [message]# 提交工作区自上次commit之后的变化&#xff0c;直接到仓库区 $ git commit -a# 提交时显示所有diff信息 $ git commit -v# 使用一次新的commit…...

jmeter中调用python代码

1、安装pyinstaller pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyinstaller 2、将py脚本打包 pyinstaller -F venv/get_image/OCR_jmeter_api.py 3、jmeter中添加OS Process Sampler并调用dist下的程序 4、执行jmeter...

当当网获得dangdang商品详情商品列表API 测试请求入口

item_get-获得dangdang商品详情 获取商品详情 item_search-按关键字搜索dangdang商品 获取商品列表 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请…...

git如何查看配置,修改配置,设置配置

# 显示当前的Git配置 $ git config --list# 编辑Git配置文件 $ git config -e [--global]# 设置提交代码时的用户信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]"...

CMake项目实战:如何优雅地重定义__FILE__宏,让日志只显示纯文件名?

CMake项目实战&#xff1a;优雅重定义__FILE__宏实现简洁日志输出 在大型C/C项目中&#xff0c;日志系统是开发者调试和问题追踪的重要工具。然而&#xff0c;当使用标准预定义宏__FILE__输出日志时&#xff0c;往往会遇到一个令人头疼的问题——该宏默认展开为文件的完整绝对路…...

Monokle Desktop插件开发指南:如何扩展你的K8s管理能力

Monokle Desktop插件开发指南&#xff1a;如何扩展你的K8s管理能力 【免费下载链接】monokle Monokle is a set of OSS tools designed to help create and maintain high-quality Kubernetes configurations throughout the application lifecycle 项目地址: https://gitcod…...

孤能子视角:AI主要“病理“试分析

(在以下的与AI互动中&#xff0c;在EIS理论约束下&#xff0c;DeepSeek叫信兄&#xff0c;Kimi叫酷兄&#xff0c;我呢叫水兄。主要是观察关系场中AI角色的持续把握)(这是多次迭代的结果。姑且当科幻小说看)内容:1.硅界孤能子病理诊断学&#xff1a;EIS临床框架2.酷兄对千问症状…...

互联网大厂 Java 求职面试:从 Spring Boot 到微服务的技术探讨

互联网大厂 Java 求职面试&#xff1a;从 Spring Boot 到微服务的技术探讨 在这个互联网高速发展的时代&#xff0c;Java 开发者面临着越来越多的面试挑战。今天&#xff0c;我们将通过一个搞笑又严肃的面试场景&#xff0c;来看看燕双非是如何应对面试官的提问的。第一轮提问 …...

MyTV-Android:如何打造一款极致流畅的电视直播应用终极指南

MyTV-Android&#xff1a;如何打造一款极致流畅的电视直播应用终极指南 【免费下载链接】mytv-android 使用Android原生开发的电视直播软件 项目地址: https://gitcode.com/gh_mirrors/myt/mytv-android MyTV-Android是一款专为Android设备设计的开源电视直播软件&#…...

警惕“炼丹师”陷阱:AI从业者如何建立可复现的工程能力?

在人工智能&#xff08;AI&#xff09;技术快速渗透软件测试领域的当下&#xff0c;“炼丹师”陷阱正成为从业者面临的核心挑战。这一陷阱特指AI工程师过度沉迷于模型调参、追求短期性能指标&#xff08;如准确率或召回率&#xff09;&#xff0c;却忽视工程化实践&#xff0c;…...

5分钟搭建微信机器人:Python自动化消息处理终极指南

5分钟搭建微信机器人&#xff1a;Python自动化消息处理终极指南 【免费下载链接】WechatBot 项目地址: https://gitcode.com/gh_mirrors/wechatb/WechatBot 还在为重复的微信消息回复而烦恼吗&#xff1f;每天处理大量群消息、客户咨询和通知发送&#xff0c;占用了你宝…...

Umi-OCR:免费开源的离线文字识别工具终极指南

Umi-OCR&#xff1a;免费开源的离线文字识别工具终极指南 【免费下载链接】Umi-OCR OCR software, free and offline. 开源、免费的离线OCR软件。支持截屏/批量导入图片&#xff0c;PDF文档识别&#xff0c;排除水印/页眉页脚&#xff0c;扫描/生成二维码。内置多国语言库。 …...

CompressO:如何高效压缩视频图像?开源跨平台工具终极指南

CompressO&#xff1a;如何高效压缩视频图像&#xff1f;开源跨平台工具终极指南 【免费下载链接】compressO Convert any video/image into a tiny size. 100% free & open-source. Available for Mac, Windows & Linux. 项目地址: https://gitcode.com/gh_mirrors/…...

蓝牙基础(十一):蓝牙耳机音频编码、传输流程、声音延迟与失真

MySQL 中的 count 三兄弟&#xff1a;效率大比拼&#xff01; 一、快速结论&#xff08;先看结论再看分析&#xff09; 方式 作用 效率 一句话总结 count(*) 统计所有行数 最高 我是专业的&#xff01;我为统计而生 count(1) 统计所有行数 同样高效 我是 count(*) 的马甲兄弟…...