From 84cea03752ee67f6339b519dfe0e04a34060b459 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com>
Date: Thu, 28 Mar 2024 22:33:01 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9A=20=E5=8F=91?=
=?UTF-8?q?=E9=80=81=E6=B6=88=E6=81=AF=E4=BD=BF=E7=94=A8WebSocketSenderApi?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../conversation/ConversationTypeEnum.java | 12 ++++-
.../im/service/inbox/InboxServiceImpl.java | 5 +-
.../service/message/MessageServiceImpl.java | 16 +++---
.../websocket/ImWebSocketMessageListener.java | 49 +++++++++++++++++++
.../websocket/message/ImReceiveMessage.java | 38 ++++++++++++++
.../im/websocket/message/ImSendMessage.java | 30 ++++++++++++
6 files changed, 140 insertions(+), 10 deletions(-)
create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java
create mode 100644 yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java
diff --git a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java
index afd6bfe7ba..091f3af3f5 100644
--- a/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java
+++ b/yudao-module-im/yudao-module-im-api/src/main/java/cn/iocoder/yudao/module/im/enums/conversation/ConversationTypeEnum.java
@@ -1,8 +1,11 @@
package cn.iocoder.yudao.module.im.enums.conversation;
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
+import java.util.Arrays;
+
/**
* IM 会话类型枚举
* 参考 “会话类型” 文档
@@ -11,12 +14,14 @@ import lombok.Getter;
*/
@Getter
@AllArgsConstructor
-public enum ConversationTypeEnum {
+public enum ConversationTypeEnum implements IntArrayValuable {
SINGLE(1, "单聊"),
GROUP(3, "群聊"),
NOTIFICATION(4, "通知会话");
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ConversationTypeEnum::getType).toArray();
+
/**
* 类型
*/
@@ -27,6 +32,11 @@ public enum ConversationTypeEnum {
*/
private final String name;
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
/**
* 生成会话编号
* @param fromUserId 发送者编号
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxServiceImpl.java
index 472d297fc8..20df49d017 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/inbox/InboxServiceImpl.java
@@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.im.dal.redis.inbox.InboxLockRedisDAO;
import cn.iocoder.yudao.module.im.dal.redis.inbox.SequenceRedisDao;
import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
import cn.iocoder.yudao.module.im.service.groupmember.GroupMemberService;
+import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
import jakarta.annotation.Resource;
import org.dromara.hutool.core.date.DateUnit;
import org.springframework.stereotype.Service;
@@ -38,7 +39,7 @@ public class InboxServiceImpl implements InboxService {
@Resource
private InboxLockRedisDAO inboxLockRedisDAO; // 收件箱的锁 Redis DAO
@Resource
- private WebSocketMessageSender webSocketMessageSender; // WebSocket消息发送器
+ private WebSocketSenderApi webSocketSenderApi;
@Resource
private GroupMemberService groupMemberService;
@@ -71,7 +72,7 @@ public class InboxServiceImpl implements InboxService {
InboxSendMessageReqVO message = BeanUtils.toBean(inboxSaveMessage, InboxSendMessageReqVO.class);
message.setSequence(userSequence);
- webSocketMessageSender.sendObject(UserTypeEnum.ADMIN.getValue(), userId, IM_MESSAGE_RECEIVE, message);
+ webSocketSenderApi.sendObject(UserTypeEnum.ADMIN.getValue(), userId, IM_MESSAGE_RECEIVE, message);
});
}
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java
index 4f837b0c53..0ca4748575 100755
--- a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/service/message/MessageServiceImpl.java
@@ -88,13 +88,15 @@ public class MessageServiceImpl implements MessageService {
messageMapper.insert(messageDO);
// 设置 InboxSaveMessageReqVO 对象
- inboxSaveMessageReqVO.setConversationType(message.getConversationType());
- inboxSaveMessageReqVO.setFromId(fromUserId);
- inboxSaveMessageReqVO.setReceiverId(message.getReceiverId());
- inboxSaveMessageReqVO.setMessageId(messageDO.getId());
- inboxSaveMessageReqVO.setContentType(message.getContentType());
- inboxSaveMessageReqVO.setContent(message.getContent());
- inboxSaveMessageReqVO.setSendTime(messageDO.getSendTime());
+ inboxSaveMessageReqVO.setConversationType(message.getConversationType())
+ .setFromId(fromUserId)
+ .setReceiverId(message.getReceiverId())
+ .setMessageId(messageDO.getId())
+ .setContentType(message.getContentType())
+ .setContent(message.getContent())
+ .setSendTime(messageDO.getSendTime())
+ .setSenderNickname(fromUser.getNickname())
+ .setSenderAvatar(fromUser.getAvatar());
// 返回 SendMessageRespVO 对象
return new SendMessageRespVO(messageDO.getId(), messageDO.getSendTime());
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
new file mode 100644
index 0000000000..21cbdbc27e
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/ImWebSocketMessageListener.java
@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.im.websocket;
+
+import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener;
+import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils;
+import cn.iocoder.yudao.module.im.websocket.message.ImSendMessage;
+import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.WebSocketSession;
+
+// TODO @hao:消息发送,使用 http 上行。因为在 cloud 框架下,我们比较难去 Listener。因为 im-server 不会自己启动 websocket 路径
+
+/**
+ * WebSocket im
+ *
+ * @author 芋道源码
+ */
+@Component
+@Slf4j
+public class ImWebSocketMessageListener implements WebSocketMessageListener {
+
+ public static final String IM_MESSAGE_RECEIVE = "im-message-receive";
+ @Resource
+ private WebSocketSenderApi webSocketSenderApi; // WebSocket消息发送器
+
+ /**
+ * 处理WebSocket消息
+ *
+ * @param session WebSocket会话
+ * @param message 发送的IM消息
+ */
+ @Override
+ public void onMessage(WebSocketSession session, ImSendMessage message) {
+ Long fromUserId = WebSocketFrameworkUtils.getLoginUserId(session); // 获取登录用户ID
+ log.info(message.toString());
+ }
+
+ /**
+ * 获取类型
+ *
+ * @return 类型
+ */
+ @Override
+ public String getType() {
+ return "im-message-send";
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java
new file mode 100644
index 0000000000..87d8df592f
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImReceiveMessage.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.im.websocket.message;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 消息发送 receive")
+@Data
+public class ImReceiveMessage {
+
+ @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @InEnum(ConversationTypeEnum.class)
+ private Integer conversationType;
+
+ @Schema(description = "发送人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long fromId; // 根据 conversationType 区分
+
+ // TODO @hao:昵称和头像,也直接发给接收人好了;
+
+ @Schema(description = "消息编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "12454")
+ private Long messageId;
+
+ @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer contentType; // 参见 ImMessageTypeEnum 枚举
+
+ @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
+ private String content;
+
+ @Schema(description = "发送时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime sendTime;
+
+ @Schema(description = "序号", requiredMode = Schema.RequiredMode.REQUIRED)
+ private Long sequence;
+
+}
\ No newline at end of file
diff --git a/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java
new file mode 100644
index 0000000000..77e37a3cb5
--- /dev/null
+++ b/yudao-module-im/yudao-module-im-biz/src/main/java/cn/iocoder/yudao/module/im/websocket/message/ImSendMessage.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.im.websocket.message;
+
+import cn.iocoder.yudao.framework.common.validation.InEnum;
+import cn.iocoder.yudao.module.im.enums.conversation.ConversationTypeEnum;
+import cn.iocoder.yudao.module.im.enums.message.MessageContentTypeEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Schema(description = "管理后台 - IM 消息发送 send")
+@Data
+public class ImSendMessage {
+
+ @Schema(description = "客户端消息编号 uuid,用于排重", requiredMode = Schema.RequiredMode.REQUIRED, example = "3331")
+ private String clientMessageId;
+
+ @Schema(description = "会话类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @InEnum(ConversationTypeEnum.class)
+ private Integer conversationType;
+
+ @Schema(description = "接收人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+ private Long receiverId; // 根据 conversationType 区分
+
+ @Schema(description = "内容类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @InEnum(MessageContentTypeEnum.class)
+ private Integer contentType;
+
+ @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED)
+ private String content;
+
+}
\ No newline at end of file