refactor: 使用事件解耦业务副作用并优化虚拟线程并发

- 新增登录成功事件,解耦在线用户缓存、登录日志和最近登录信息更新
  - 新增在线用户清理事件,角色授权变更后异步清理受影响用户会话
  - 新增 OSS 配置变更事件,统一处理配置初始化、删除和默认配置切换后的缓存刷新
  - 新增工作流抄送、待办消息、结果消息事件,拆分全局监听器中的副作用逻辑
  - 扩展 ThreadUtils 支持带返回值的虚拟线程批量执行
  - 在线用户监控批量读取 Redis 会话信息时使用虚拟线程并发处理
  - OSS 多文件查询、URL 解析和 DTO 转换使用虚拟线程并发处理
  - 工作流办理人回显和用户解析按类型并发查询
  - 工作流多渠道消息发送改为并发执行
  - WebSocket 与 SSE 广播消息按用户并发发送
This commit is contained in:
疯狂的狮子Li
2026-05-16 18:44:24 +08:00
parent f171ac03c4
commit 84afd6e6c0
23 changed files with 579 additions and 146 deletions
@@ -3,6 +3,7 @@ package org.dromara.common.push.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.ThreadUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.push.constant.MessageConstants;
import org.dromara.common.push.dto.PushDTO;
@@ -227,9 +228,11 @@ public class SseEmitterSessionManager implements PushSessionManager {
* @param message 要发送的消息内容
*/
public void sendMessage(String message) {
for (Long userId : USER_TOKEN_EMITTERS.keySet()) {
sendMessage(userId, message);
}
List<Long> userIds = new ArrayList<>(USER_TOKEN_EMITTERS.keySet());
Runnable[] sendTasks = userIds.stream()
.map(userId -> (Runnable) () -> sendMessage(userId, message))
.toArray(Runnable[]::new);
ThreadUtils.virtualInvokeAll(sendTasks);
}
/**
@@ -3,6 +3,7 @@ package org.dromara.common.push.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.utils.ThreadUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.push.dto.PushDTO;
import org.dromara.common.push.properties.MessageProperties;
@@ -181,7 +182,11 @@ public class WebSocketSessionManager implements PushSessionManager {
if (payload == null) {
return;
}
USER_TOKEN_SESSIONS.keySet().forEach(userId -> sendMessage(userId, payload));
List<Long> userIds = new ArrayList<>(USER_TOKEN_SESSIONS.keySet());
Runnable[] sendTasks = userIds.stream()
.map(userId -> (Runnable) () -> sendMessage(userId, payload))
.toArray(Runnable[]::new);
ThreadUtils.virtualInvokeAll(sendTasks);
}
/**