基于若依ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(三)
更多ruoyi-nbcio功能请看演示系统
gitee源代码地址
前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio
演示地址:RuoYi-Nbcio后台管理系统
1、上一节说到RedisReceiver ,这里有调用了NbcioRedisListener自定义业务监听,如下:
package com.ruoyi.common.redis.listener;import com.ruoyi.common.base.BaseMap;/*** 自定义消息监听* @author nbacheng* @date 2023-09-20*/public interface NbcioRedisListener {void onMessage(BaseMap message);
}
2、实现这个代码如下:
package com.ruoyi.common.websocket;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import com.ruoyi.common.base.BaseMap;
import com.ruoyi.common.constant.CommonSendStatus;
import com.ruoyi.common.redis.listener.NbcioRedisListener;import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;/*** 监听消息(采用redis发布订阅方式发送消息)*/
@Slf4j
@Component
public class SocketHandler implements NbcioRedisListener {@Autowiredprivate WebSocketServer webSocket;@Overridepublic void onMessage(BaseMap map) {log.info("【SocketHandler消息】Redis Listerer:" + map.toString());String userId = map.get("userId");String message = map.get("message");if (ObjectUtil.isNotEmpty(userId)) {webSocket.pushMessage(userId, message);//app端消息推送webSocket.pushMessage(userId+CommonSendStatus.APP_SESSION_SUFFIX, message);} else {webSocket.pushMessage(message);}}
这里进行了websocket的服务器给用户推送,同时之前第一个节里公共类方法也同时往两个表增加数据,以便失败后后续可以进行发送,以确保能真正通知到用户。
3、接下来就是需要在用户提起流程发给审批人进行消息发送了
package com.ruoyi.flowable.listener;import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.api.delegate.event.FlowableEventType;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.stereotype.Component;import com.ruoyi.common.core.service.CommonService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.model.LoginUser;import javax.annotation.Resource;/*** 全局监听-工作流待办消息提醒** @author nbacheng*/
@Slf4j
@Component
@RequiredArgsConstructor
public class TaskCreateListener implements FlowableEventListener {private final TaskService taskService;@Resourceprivate CommonService commonService;@Resourceprotected RepositoryService repositoryService;@Resourceprotected HistoryService historyService;@Overridepublic void onEvent(FlowableEvent flowableEvent) {FlowableEventType type = flowableEvent.getType();if (type == FlowableEngineEventType.TASK_ASSIGNED) { if(flowableEvent instanceof org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl ) {TaskEntity taskEntity = (TaskEntity) ((org.flowable.engine.delegate.event.impl.FlowableEntityEventImpl) flowableEvent).getEntity();String taskId = taskEntity.getId();String procInsId = taskEntity.getProcessInstanceId();HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).singleResult();String businessKey = historicProcessInstance.getBusinessKey();String deployId = historicProcessInstance.getDeploymentId();String startUserId = historicProcessInstance.getStartUserId();//获取任务接收人String receiver = taskEntity.getAssignee();if (StringUtils.isNotEmpty(receiver)) {//发送提醒消息String category = "";if(taskService.getVariables(taskId).get("category") != null) {category = taskService.getVariables(taskId).get("category").toString();}LoginUser loginUser = commonService.getLoginUser();String taskMessageUrl;if(StringUtils.isNotBlank(businessKey)) {taskMessageUrl = "<a href=" + commonService.getBaseUrl() + "?procInsId=" + procInsId + "&deployId=" + deployId + "&taskId=" + taskId + "&businessKey=" + businessKey + "&category=" + category+ "&finished=true" + ">点击这个进行处理</a>" ;}else {taskMessageUrl = "<a href=" + commonService.getBaseUrl() + "?procInsId=" + procInsId + "&deployId=" + deployId + "&taskId=" + taskId + "&businessKey" + "&category=" + category + "&finished=true" + ">点击这个进行处理</a>" ;}String msgContent = "流程待办通知" + taskMessageUrl;if(!StringUtils.equals(startUserId, receiver) || !StringUtils.equals((loginUser.getUserId()).toString(),receiver)) {//发起人或登录人自己不发送log.info("流程待办通知给:" + receiver);commonService.sendSysNotice(loginUser.getUserId().toString(), receiver, "流程待办通知", msgContent, Constants.MSG_CATEGORY_3);//setMsgCategory=3是待办}}}} }@Overridepublic boolean isFailOnException() {return false;}@Overridepublic boolean isFireOnTransactionLifecycleEvent() {return false;}@Overridepublic String getOnTransaction() {return null;}
}
相关文章:
基于若依ruoyi-nbcio增加flowable流程待办消息的提醒,并提供右上角的红字数字提醒(三)
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 1、上一节说到RedisReceiver ,这里有调用了NbcioRedisListener自定义业务监听,如下…...
用友第五届开发者大赛初赛晋级公示,复赛火热进行中!
用友第五届开发者大赛初赛晋级公示,复赛火热进行中! 自7月13日鸣锣揭幕,9月6日各赛道作品初评工作完成,历时近两月,用友第五届企业云服务开发者大赛初赛阶段顺利落下帷幕。作为备受各界开发者关注的赛事,本…...
SSL证书如何做到保障网站安全?
当网站显示不安全时,用户会在头脑中产生该网站是否合法的疑问,如果是购物网站或者购物商城,那意味着可能会损失大部分的用户。而SSL证书能有效保障网站的安全性,轻松解决网站不被用户信任的问题。那么,SSL证书究竟是如…...
C# Onnx Yolov8 Detect Poker 扑克牌识别
效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System…...
想要精通算法和SQL的成长之路 - 最长等差数列
想要精通算法和SQL的成长之路 - 最长等差数列 前言一. 最长等差数列 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 最长等差数列 原题链接 思路: 我们假设dp[i][j] 为:以num[i]为结尾,以j为公差的最长等差子序列的长度。由此可知&a…...
【简单的自动曝光】python实现-附ChatGPT解析
1.题目 一个图像有 n 个像素点,存储在一个长度为 n 的数组 img 里, 每个像素点的取值范围[0,255] 的正整数。 请你给图像每个像素点值,加上一个整数 k (可以是负数),得到新图 newImg , 使得新图newImg 的所有像素平均值最接近中位值 128。 请输出这个整数 k。 输入描述 n …...
网工内推 | 运维工程师,CCNP认证优先,周末双休,多次调薪机会
01 驻场运维 职责描述: 1、驻场某大型汽车整车厂,配合客户完成网络相关(路由交换)的项目。 2、按照客户要求,与项目组配合共同完成项目前期调研,设计,规划,项目中期调试测试&#…...
LeetCode 1337. The K Weakest Rows in a Matrix【数组,二分,堆,快速选择,排序】1224
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
如何使用Spring提供的Retry
0、本例中使用的是 springboot-2.0.4.RELEASE,jdk1.8 1、导包。需要注意版本。2.0.0需要spring6和jdk17 <dependency><groupId>org.springframework.retry</groupId><artifactId>spring-retry</artifactId><version>1.3.4<…...
【ONE·Linux || 进程间通信】
总言 进程间通信:简述进程间通信,介绍一些通信方式,管道通信(匿名、名命)、共享内存等。 文章目录 总言1、进程间通信简述2、管道2.1、简介2.2、匿名管道2.2.1、匿名管道的原理2.2.2、编码理解:用fork来共…...
207.Flink(二):架构及核心概念,flink从各种数据源读取数据,各种算子转化数据,将数据推送到各数据源
一、Flink架构及核心概念 1.系统架构 JobMaster是JobManager中最核心的组件,负责处理单独的作业(Job)。一个job对应一个jobManager 2.并行度 (1)并行度(Parallelism)概念 一个特定算子的子任务(subtask)的个数被称之为其并行度(parallelism)。这样,包含并行子任…...
debian终端快捷键设置
为了方便使用图形化debian,快捷调出shell终端是提升工作学习效率的最重要的一步。 1.首先点击右上角,选择设置 2.点击键盘,选择快捷键,并创建自定义快捷键 3.点击添加快捷键 4.根据图中提示创建快捷键 Name: Terminal Command…...
原生ajax
什么是Ajax Asynchronous JavaScript and xml 异步的 js 和 xml(数据承载方式) ,本质:使用js提供的异步对象XMLHttpRequest 异步的向服务器提交请求,并且接受服务器响应回来的数据。 使用ajax 1.创建异步对象 var xhrnew XMLHttp…...
面试题库(五):并发编程
多线程类的使用 java线程同步有哪些方法、各自的优缺点synchronized 和ReentrantLock区别,可重入锁是什么?threadlocal有什么用Java中创建线程有几种方式?分别是? 当主线程执行结束后,子线程还会继续执行下去吗?JUC中有哪些常用的集合?(项目中用到的)CopyOnWriteArray…...
Android FileProvider笔记
一、FileProvider是什么 通过FileProvider.getUriForFile(NonNull Context context, NonNull String authority, NonNull File file)方法获得一个有临时权限的Uri给客户端用来访问本APP文件。 当然看FileProvider类的注释更加详细 二、代码示例 <providerandroid:name&q…...
华为云云耀云服务器L实例评测 |云服务器选购
华为云耀云服务器 L 实例是一款轻量级云服务器,开通选择实例即可立刻使用,不需要用户再对服务器进行基础配置。新用户还有专享优惠,2 核心 2G 内存 3M 带宽的服务器只要 89 元/年,可以点击华为云云耀云服务器 L 实例购买地址去购买…...
2023-09-22 LeetCode每日一题(将钱分给最多的儿童)
2023-09-22每日一题 一、题目编号 2591. 将钱分给最多的儿童二、题目链接 点击跳转到题目位置 三、题目描述 给你一个整数 money ,表示你总共有的钱数(单位为美元)和另一个整数 children ,表示你要将钱分配给多少个儿童。 你…...
功能测试的重要性
前言 在软件开发领域,功能测试是确保软件质量的关键步骤之一。正如其名称所示,功能测试是验证软件产品是否具有其描述的功能和符合预期结果的过程。这种类型的测试非常重要,因为它不仅可以帮助团队检测潜在的缺陷并提高软件品质,…...
《Linux高性能服务器编程》--高级I/O函数
目录 1--Pipe() 2--dup() 和 dup2() 3--readv() 和 writev() 4--sendfile() 5--mmap() 和 munmap() 6--spice() 7--tea() 8--fcntl() 1--Pipe() #include <unistd.h> int pipe(int fd[2]); // 成功返回0,失败返回-1 pipe() 函数可用于创建一个管道&a…...
算法通关村 | 透彻理解动态规划
1. 斐波那契数列 1,1,2,3,5,8,13,..... f(n) f(n-1) f(n-2) 代码实现 public static int count_2 0;public int fibonacci(int n){if (n < 2){count_2;return n;}int f1 1;int f2 2;i…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
