切面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.背景 产品需要实现一个待办提醒功能,就是核心业务发生变更即提醒业务员去处理相关业务。譬如:订单上传了支付凭证,那么就会提醒相关业务员去待办列表操办。 2.表设计 其实表设计主要是两张表sys_todo、sys_todo_detail 一张是待办核心表…...
SAP 调取http的x-www-form-urlencoded形式的接口
一、了解下x-www-form-urlencoded形式对于SAP来说有啥区别 简单来说, 1.raw格式就是标准的json格式:{“Name”:“John Smith”,“Age”: 23} 2.x-www格式是要转化一下的: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,一般不会用127.0.0.1,::1这样的本地回环地址,可以过滤掉,如果想要获取当前真正在使用的地址,得通过net.Dail去连一下才知道 获取ip地址 func main() {fmt.Println(getIpv4())fmt.Println…...
【Computer Vision Foundation】全球计算机视觉基金会论文网
计算机视觉基金会(Computer Vision Foundation,简称CVF)是一个致力于推动计算机视觉领域研究和发展的组织。以下是关于计算机视觉基金会的一些基本信息: 成立目的: CVF成立的目的是促进计算机视觉领域的学术研究、技术…...
计网(复习自用)
计算机网络 1.概述 1.1概念 含义 计算机网络:是一个将分散的。具有独立功能的计算机系统,通过通信设备和线路连接起来,由功能完善的软件实现资源共享和信息传递的系统。 简单点说,计算机网络是互联的,自治的计算机集…...
安徽省广德市选择云轴科技ZStack Cloud云平台建设县级智慧城市
信创是数字中国建设的重要组成部分,也是数字经济发展的关键推动力量。作为云基础软件企业,云轴科技ZStack产品矩阵全面覆盖数据中心云基础设施,ZStack信创云首批通过可信云《一云多芯IaaS平台能力要求》先进级,是其中唯一兼容四种…...
【计算思维】蓝桥杯STEMA 科技素养考试真题及解析 6
1、明明买了一个扫地机器人,可以通过以下指令控制机器人运动: F:向前走 10 个单位长度 L:原地左转 90 度 R:原地右转 90 度 机器人初始方向向右,需要按顺序执行以下那条指令,才能打扫完下图中的道路 A、F-L-F-R-F-F-R-F-L-F B、F-R-F-L-F-F…...
nuxt3项目修改端口号
nuxt的默认端口号是3000 一、修改开发环境端口号 方式一:使用环境变量配置,设置(PORT 或 NUXT_PORT) # .env PORT3001 #http://localhost:3001/ NITRO_PORT3001 #http://localhost:3001/ 方式二:nuxt.config.ts里配置…...
c语言中使用openssl对rsa私钥解密
单次加密数据的最大长度(block_len),由RSA秘钥模长RSA_size()和填充模式有关 填充模式:RSA_PKCS1_PADDING, block_lenRSA_size() - 11填充模式:RSA_PKCS1_OAEP_PADDING,block_lenRSA_size() - 4…...
mysql中数据是如何被用B+树查询到的
innoDB是按照页为单位读写的 那页中有很多行数据,是怎么执行查询的呢,首先我们肯定,是以单向列表形式存储的,提高了增删的效率,但是查询效率低。所以实际上对页中的行数据进行了优化,能以二分的方式进行查…...
Redisson 分布式锁的最佳实践
Redisson 分布式锁的最佳实践 第一、添加依赖第二、添加redisson配置类第三、添加测试类测试结果扩展知识redisson锁中lock方法和tryLock方法有什么区别锁续约 注意事项 引言 在现代分布式系统中,处理并发问题是至关重要的。分布式锁是解决这类问题的关键工具之一。…...
ArkTS声明式开发范式
装饰器 用来装饰类、结构体、方法以及变量,赋予其特殊的含义,如上述示例中 Entry 、 Component 、 State 都是装饰器。 Component 表示这是个自定义组件; Entry 则表示这是个入口组件; State 表示组件中的状态变量,…...
史诗级云故障敲响警钟,应用保障不能没有“连续键”!
近日,知名云服务商出现一次史诗级的云故障:全球所有区域/所有服务同时异常,故障持续长达3小时之多,云上众多应用受到极大影响。 如今,在一个充满不确定性和复杂性的数字化时代,哪怕是顶级云服务商亦不能避…...
SSH连接远程服务器报错:WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED 解决方法
一.错误描述 报错信息里提示了路径信息/root/.ssh/known_hosts:20 二.解决方案 方法一 输入以下指令: ssh-keygen -R XXX(需要连接远程服务器的ip) 按照我的例子ip:10.165.7.136,会返回以下信息: 重新尝试连接: 输…...
数据库——查询连续的月份
一、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之后的变化,直接到仓库区 $ 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(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请…...
git如何查看配置,修改配置,设置配置
# 显示当前的Git配置 $ git config --list# 编辑Git配置文件 $ git config -e [--global]# 设置提交代码时的用户信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]"...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
