From 58d6f15cc4502c94595a915007e400b76fbb295e Mon Sep 17 00:00:00 2001 From: liuhanqing <447067298@qq.com> Date: Sun, 24 Jan 2021 23:25:46 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90message=E3=80=91=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=A2=9E=E5=8A=A0websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message-sdk-websocket/README.md | 1 + .../message-sdk-websocket/pom.xml | 35 +++++++ .../websocket/manager/WebSocketManager.java | 95 +++++++++++++++++++ .../websocket/server/WebSocketEndpoint.java | 78 +++++++++++++++ .../message-spring-boot-starter/pom.xml | 5 + .../starter/GunsMessageAutoConfiguration.java | 16 +++- kernel-s-message/pom.xml | 1 + 7 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 kernel-s-message/message-sdk-websocket/README.md create mode 100644 kernel-s-message/message-sdk-websocket/pom.xml create mode 100644 kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/manager/WebSocketManager.java create mode 100644 kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/server/WebSocketEndpoint.java diff --git a/kernel-s-message/message-sdk-websocket/README.md b/kernel-s-message/message-sdk-websocket/README.md new file mode 100644 index 000000000..c3097283d --- /dev/null +++ b/kernel-s-message/message-sdk-websocket/README.md @@ -0,0 +1 @@ +系统消息websocket的sdk,用于将消息发送给在线用户,并提供相应接口 \ No newline at end of file diff --git a/kernel-s-message/message-sdk-websocket/pom.xml b/kernel-s-message/message-sdk-websocket/pom.xml new file mode 100644 index 000000000..0bc7a8c83 --- /dev/null +++ b/kernel-s-message/message-sdk-websocket/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + + cn.stylefeng.roses + kernel-s-message + 1.0.0 + ../pom.xml + + + message-sdk-websocket + + jar + + + + + + cn.stylefeng.roses + message-api + 1.0.0 + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + + diff --git a/kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/manager/WebSocketManager.java b/kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/manager/WebSocketManager.java new file mode 100644 index 000000000..2d7d93dc8 --- /dev/null +++ b/kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/manager/WebSocketManager.java @@ -0,0 +1,95 @@ +package cn.stylefeng.roses.kernel.message.websocket.manager; + +import org.springframework.util.CollectionUtils; + +import javax.websocket.Session; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author liuhq + */ +public class WebSocketManager { + private static final ConcurrentHashMap> userIdSessionMap = new ConcurrentHashMap<>(); + + /** + * 添加用户ID相关的Session + * + * @param userId 用户id + * @param session 用户websocketSession + * @author liuhanqing + * @date 2021/1/24 22:08 + */ + public static void add(Long userId, Session session) { + userIdSessionMap.computeIfAbsent(userId, v -> new ArrayList<>()).add(session); + } + + /** + * 根据用户ID获取Session + * + * @param userId 用户id + * @return List 用户websocketSession集合 + * @author liuhanqing + * @date 2021/1/24 22:10 + */ + public static List getSessionByUserId(Long userId) { + return userIdSessionMap.get(userId); + } + + /** + * 移除失效的Session + * + * @param userId 用户id + * @param session 用户websocketSession + * @author liuhanqing + * @date 2021/1/24 22:11 + */ + public static void removeSession(Long userId, Session session) { + if (session == null) { + return; + } + List webSessoin = userIdSessionMap.get(userId); + if (webSessoin == null || CollectionUtils.isEmpty(webSessoin)) { + return; + } + webSessoin.remove(session); + } + + /** + * 获取链接用户集合 + * + * @author liuhanqing + * @date 2021/1/24 22:11 + */ + public static Set getUserList() { + return userIdSessionMap.keySet(); + } + + /** + * 发送消息 + * + * @param userId 用户id + * @param message 消息 + * @author liuhanqing + * @date 2021/1/24 22:11 + */ + public static void sendMessage(Long userId, String message){ + for(Session userSession: getSessionByUserId(userId)){ + userSession.getAsyncRemote().sendText(message); + } + } + /** + * 发送消息 + * + * @param message 消息 + * @author liuhanqing + * @date 2021/1/24 22:11 + */ + public static void sendMessageToAll(String message){ + for (Long userId : WebSocketManager.getUserList()) { + sendMessage(userId, message); + } + } +} diff --git a/kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/server/WebSocketEndpoint.java b/kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/server/WebSocketEndpoint.java new file mode 100644 index 000000000..97fe3d064 --- /dev/null +++ b/kernel-s-message/message-sdk-websocket/src/main/java/cn/stylefeng/roses/kernel/message/websocket/server/WebSocketEndpoint.java @@ -0,0 +1,78 @@ +package cn.stylefeng.roses.kernel.message.websocket.server; + +import cn.stylefeng.roses.kernel.message.websocket.manager.WebSocketManager; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.websocket.*; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; + +/** + * websocket服务端 + * + * @author liuhanqing + * @date 2021/1/24 22:26 + */ +@Slf4j +@Component +@ServerEndpoint("/message/websocket/{userId}") +public class WebSocketEndpoint { + + + /** + * 连接建立成功后调用 + * + * @param userId 用户id + * @param session 用户websocketSession + * @author liuhanqing + * @date 2021/1/24 22:27 + */ + @OnOpen + public void onOpen(@PathParam(value = "userId") Long userId, Session session) { + // 添加到链接管理 + WebSocketManager.add(userId, session); + // 返回消息 + session.getAsyncRemote().sendText("WebSocket连接成功"); + } + + /** + * 连接关闭时调用 + * + * @author liuhanqing + * @date 2021/1/24 22:29 + */ + @OnClose + public void onClose(@PathParam(value = "userId") Long userId, Session session) { + // 从map中删除 + WebSocketManager.removeSession(userId, session); + } + + /** + * 收到客户端消息后调用 + * + * @param message 客户端发送过来的消息 + * @param session 用户websocketSession + * @author liuhanqing + * @date 2021/1/24 22:29 + */ + @OnMessage + public void onMessage(String message, Session session) { + log.info("来自客户端的消息:" + message); + } + + /** + * 发生错误时回调 + * + * @param session 用户信息 + * @param error 错误 + * @author liuhanqing + * @date 2021/1/24 22:29 + */ + @OnError + public void onError(Session session, Throwable error) { + log.error("WebSocket发生错误"); + error.printStackTrace(); + } + +} \ No newline at end of file diff --git a/kernel-s-message/message-spring-boot-starter/pom.xml b/kernel-s-message/message-spring-boot-starter/pom.xml index 4f3ad1332..8e524f516 100644 --- a/kernel-s-message/message-spring-boot-starter/pom.xml +++ b/kernel-s-message/message-spring-boot-starter/pom.xml @@ -32,6 +32,11 @@ 1.0.0 + + cn.stylefeng.roses + message-sdk-websocket + 1.0.0 + diff --git a/kernel-s-message/message-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/message/starter/GunsMessageAutoConfiguration.java b/kernel-s-message/message-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/message/starter/GunsMessageAutoConfiguration.java index a2c26e978..4ff570dfe 100644 --- a/kernel-s-message/message-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/message/starter/GunsMessageAutoConfiguration.java +++ b/kernel-s-message/message-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/message/starter/GunsMessageAutoConfiguration.java @@ -1,6 +1,9 @@ package cn.stylefeng.roses.kernel.message.starter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * 系统消息的自动配置 @@ -11,6 +14,17 @@ import org.springframework.context.annotation.Configuration; @Configuration public class GunsMessageAutoConfiguration { - + /** + * 开启WebSocket功能 + * + * @return serverEndpointExporter + * @author liuhanqing + * @date 2021/01/24 22:09 + */ + @Bean + @ConditionalOnMissingBean(ServerEndpointExporter.class) + public ServerEndpointExporter serverEndpointExporter() { + return new ServerEndpointExporter(); + } } \ No newline at end of file diff --git a/kernel-s-message/pom.xml b/kernel-s-message/pom.xml index 728ea6b52..b3c1b9155 100644 --- a/kernel-s-message/pom.xml +++ b/kernel-s-message/pom.xml @@ -19,6 +19,7 @@ message-api message-business message-sdk-db + message-sdk-websocket message-spring-boot-starter