基于若依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…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
