From 74853f4d9c03bb8209e50de9f8bb47638ea29f9e Mon Sep 17 00:00:00 2001 From: dataprince Date: Wed, 17 Jan 2024 20:24:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0websocket=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../ruoyi/web/controller/AuthController.java | 1 + .../ruoyi/web/domain/vo/LoginTenantVo.java | 5 + ruoyi-common/pom.xml | 1 + ruoyi-common/ruoyi-common-bom/pom.xml | 7 ++ ruoyi-common/ruoyi-common-websocket/pom.xml | 40 +++++++ .../websocket/config/WebSocketConfig.java | 59 ++++++++++ .../properties/WebSocketProperties.java | 26 +++++ .../constant/WebSocketConstants.java | 28 +++++ .../websocket/dto/WebSocketMessageDto.java | 29 +++++ .../handler/FlexWebSocketHandler.java | 101 ++++++++++++++++ .../holder/WebSocketSessionHolder.java | 42 +++++++ .../interceptor/FlexWebSocketInterceptor.java | 51 ++++++++ .../listener/WebSocketTopicListener.java | 43 +++++++ .../websocket/utils/WebSocketUtils.java | 110 ++++++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + 16 files changed, 545 insertions(+), 1 deletion(-) create mode 100644 ruoyi-common/ruoyi-common-websocket/pom.xml create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/WebSocketConfig.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/properties/WebSocketProperties.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/constant/WebSocketConstants.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/dto/WebSocketMessageDto.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/handler/FlexWebSocketHandler.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/holder/WebSocketSessionHolder.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/interceptor/FlexWebSocketInterceptor.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/listener/WebSocketTopicListener.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/utils/WebSocketUtils.java create mode 100644 ruoyi-common/ruoyi-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/pom.xml b/pom.xml index ae17218..2a32c7a 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ 1.3.6 0.2.0 5.8.24 - 3.25.2 + 3.26.0 2.2.7 2.14.4 3.2.0 diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java index a2b8024..4ca7575 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/AuthController.java @@ -134,6 +134,7 @@ public class AuthController { StringUtils.equals(vo.getDomain(), host)); // 返回对象 LoginTenantVo vo = new LoginTenantVo(); + vo.setTenantEnabled(true); vo.setVoList(CollUtil.isNotEmpty(list) ? list : voList); return R.ok(vo); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java b/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java index 521797a..cc42e96 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/domain/vo/LoginTenantVo.java @@ -12,6 +12,11 @@ import java.util.List; @Data public class LoginTenantVo { + /** + * 租户开关 + */ + private Boolean tenantEnabled; + /** * 租户对象列表 */ diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index f6d7b7c..7603dbd 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -26,6 +26,7 @@ ruoyi-common-springdoc ruoyi-common-tenant ruoyi-common-web + ruoyi-common-websocket ruoyi-common diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml index f0644d4..a277116 100644 --- a/ruoyi-common/ruoyi-common-bom/pom.xml +++ b/ruoyi-common/ruoyi-common-bom/pom.xml @@ -117,6 +117,13 @@ ${revision} + + + com.ruoyi + ruoyi-common-websocket + ${revision} + + diff --git a/ruoyi-common/ruoyi-common-websocket/pom.xml b/ruoyi-common/ruoyi-common-websocket/pom.xml new file mode 100644 index 0000000..bfdba51 --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/pom.xml @@ -0,0 +1,40 @@ + + + + com.ruoyi + ruoyi-common + ${revision} + + 4.0.0 + + ruoyi-common-websocket + + + ruoyi-common-websocket 模块 + + + + + com.ruoyi + ruoyi-common-core + + + com.ruoyi + ruoyi-common-redis + + + com.ruoyi + ruoyi-common-security + + + com.ruoyi + ruoyi-common-json + + + org.springframework.boot + spring-boot-starter-websocket + + + diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/WebSocketConfig.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/WebSocketConfig.java new file mode 100644 index 0000000..e5190fd --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/WebSocketConfig.java @@ -0,0 +1,59 @@ +package com.ruoyi.common.websocket.config; + +import cn.hutool.core.util.StrUtil; +import com.ruoyi.common.websocket.config.properties.WebSocketProperties; +import com.ruoyi.common.websocket.handler.FlexWebSocketHandler; +import com.ruoyi.common.websocket.interceptor.FlexWebSocketInterceptor; +import com.ruoyi.common.websocket.listener.WebSocketTopicListener; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.server.HandshakeInterceptor; + +/** + * WebSocket 配置 + * + * @author zendwang + */ +@AutoConfiguration +@ConditionalOnProperty(value = "websocket.enabled", havingValue = "true") +@EnableConfigurationProperties(WebSocketProperties.class) +@EnableWebSocket +public class WebSocketConfig { + + @Bean + public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor handshakeInterceptor, + org.springframework.web.socket.WebSocketHandler webSocketHandler, + WebSocketProperties webSocketProperties) { + if (StrUtil.isBlank(webSocketProperties.getPath())) { + webSocketProperties.setPath("/websocket"); + } + + if (StrUtil.isBlank(webSocketProperties.getAllowedOrigins())) { + webSocketProperties.setAllowedOrigins("*"); + } + + return registry -> registry + .addHandler(webSocketHandler, webSocketProperties.getPath()) + .addInterceptors(handshakeInterceptor) + .setAllowedOrigins(webSocketProperties.getAllowedOrigins()); + } + + @Bean + public HandshakeInterceptor handshakeInterceptor() { + return new FlexWebSocketInterceptor(); + } + + @Bean + public org.springframework.web.socket.WebSocketHandler webSocketHandler() { + return new FlexWebSocketHandler(); + } + + @Bean + public WebSocketTopicListener topicListener() { + return new WebSocketTopicListener(); + } +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/properties/WebSocketProperties.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/properties/WebSocketProperties.java new file mode 100644 index 0000000..97ce992 --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/config/properties/WebSocketProperties.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.websocket.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * WebSocket 配置项 + * + * @author zendwang + */ +@ConfigurationProperties("websocket") +@Data +public class WebSocketProperties { + + private Boolean enabled; + + /** + * 路径 + */ + private String path; + + /** + * 设置访问源地址 + */ + private String allowedOrigins; +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/constant/WebSocketConstants.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/constant/WebSocketConstants.java new file mode 100644 index 0000000..8c88832 --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/constant/WebSocketConstants.java @@ -0,0 +1,28 @@ +package com.ruoyi.common.websocket.constant; + +/** + * websocket的常量配置 + * + * @author zendwang + */ +public interface WebSocketConstants { + /** + * websocketSession中的参数的key + */ + String LOGIN_USER_KEY = "loginUser"; + + /** + * 订阅的频道 + */ + String WEB_SOCKET_TOPIC = "global:websocket"; + + /** + * 前端心跳检查的命令 + */ + String PING = "ping"; + + /** + * 服务端心跳恢复的字符串 + */ + String PONG = "pong"; +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/dto/WebSocketMessageDto.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/dto/WebSocketMessageDto.java new file mode 100644 index 0000000..0b38ed1 --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/dto/WebSocketMessageDto.java @@ -0,0 +1,29 @@ +package com.ruoyi.common.websocket.dto; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.List; + +/** + * 消息的dto + * + * @author zendwang + */ +@Data +public class WebSocketMessageDto implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 需要推送到的session key 列表 + */ + private List sessionKeys; + + /** + * 需要发送的消息 + */ + private String message; +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/handler/FlexWebSocketHandler.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/handler/FlexWebSocketHandler.java new file mode 100644 index 0000000..2dd164c --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/handler/FlexWebSocketHandler.java @@ -0,0 +1,101 @@ +package com.ruoyi.common.websocket.handler; + +import com.ruoyi.common.core.core.domain.model.LoginUser; +import com.ruoyi.common.websocket.constant.WebSocketConstants; +import com.ruoyi.common.websocket.dto.WebSocketMessageDto; +import com.ruoyi.common.websocket.holder.WebSocketSessionHolder; +import com.ruoyi.common.websocket.utils.WebSocketUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.socket.*; +import org.springframework.web.socket.handler.AbstractWebSocketHandler; + +import java.util.List; + +/** + * WebSocketHandler 实现类 + * + * @author zendwang + */ +@Slf4j +public class FlexWebSocketHandler extends AbstractWebSocketHandler { + + /** + * 连接成功后 + */ + @Override + public void afterConnectionEstablished(WebSocketSession session) { + LoginUser loginUser = (LoginUser) session.getAttributes().get(WebSocketConstants.LOGIN_USER_KEY); + WebSocketSessionHolder.addSession(loginUser.getUserId(), session); + log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); + } + + /** + * 处理发送来的文本消息 + * + * @param session + * @param message + * @throws Exception + */ + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + LoginUser loginUser = (LoginUser) session.getAttributes().get(WebSocketConstants.LOGIN_USER_KEY); + List userIds = List.of(loginUser.getUserId()); + WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto(); + webSocketMessageDto.setSessionKeys(userIds); + webSocketMessageDto.setMessage(message.getPayload()); + WebSocketUtils.publishMessage(webSocketMessageDto); + } + + @Override + protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception { + super.handleBinaryMessage(session, message); + } + + /** + * 心跳监测的回复 + * + * @param session + * @param message + * @throws Exception + */ + @Override + protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception { + WebSocketUtils.sendPongMessage(session); + } + + /** + * 连接出错时 + * + * @param session + * @param exception + * @throws Exception + */ + @Override + public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { + log.error("[transport error] sessionId: {} , exception:{}", session.getId(), exception.getMessage()); + } + + /** + * 连接关闭后 + * + * @param session + * @param status + */ + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { + LoginUser loginUser = (LoginUser) session.getAttributes().get(WebSocketConstants.LOGIN_USER_KEY); + WebSocketSessionHolder.removeSession(loginUser.getUserId()); + log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType()); + } + + /** + * 是否支持分片消息 + * + * @return + */ + @Override + public boolean supportsPartialMessages() { + return false; + } + +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/holder/WebSocketSessionHolder.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/holder/WebSocketSessionHolder.java new file mode 100644 index 0000000..6bca46b --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/holder/WebSocketSessionHolder.java @@ -0,0 +1,42 @@ +package com.ruoyi.common.websocket.holder; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.web.socket.WebSocketSession; + +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * WebSocketSession 用于保存当前所有在线的会话信息 + * + * @author zendwang + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class WebSocketSessionHolder { + + private static final Map USER_SESSION_MAP = new ConcurrentHashMap<>(); + + public static void addSession(Long sessionKey, WebSocketSession session) { + USER_SESSION_MAP.put(sessionKey, session); + } + + public static void removeSession(Long sessionKey) { + if (USER_SESSION_MAP.containsKey(sessionKey)) { + USER_SESSION_MAP.remove(sessionKey); + } + } + + public static WebSocketSession getSessions(Long sessionKey) { + return USER_SESSION_MAP.get(sessionKey); + } + + public static Set getSessionsAll() { + return USER_SESSION_MAP.keySet(); + } + + public static Boolean existSession(Long sessionKey) { + return USER_SESSION_MAP.containsKey(sessionKey); + } +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/interceptor/FlexWebSocketInterceptor.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/interceptor/FlexWebSocketInterceptor.java new file mode 100644 index 0000000..244e0b7 --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/interceptor/FlexWebSocketInterceptor.java @@ -0,0 +1,51 @@ +package com.ruoyi.common.websocket.interceptor; + +import com.ruoyi.common.core.core.domain.model.LoginUser; +import com.ruoyi.common.security.utils.LoginHelper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.socket.WebSocketHandler; +import org.springframework.web.socket.server.HandshakeInterceptor; + +import java.util.Map; + +import static com.ruoyi.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY; + +/** + * WebSocket握手请求的拦截器 + * + * @author zendwang + */ +@Slf4j +public class FlexWebSocketInterceptor implements HandshakeInterceptor { + + /** + * 握手前 + * + * @param request request + * @param response response + * @param wsHandler wsHandler + * @param attributes attributes + * @return 是否握手成功 + */ + @Override + public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) { + LoginUser loginUser = LoginHelper.getLoginUser(); + attributes.put(LOGIN_USER_KEY, loginUser); + return true; + } + + /** + * 握手后 + * + * @param request request + * @param response response + * @param wsHandler wsHandler + * @param exception 异常 + */ + @Override + public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { + + } +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/listener/WebSocketTopicListener.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/listener/WebSocketTopicListener.java new file mode 100644 index 0000000..33c41f5 --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/listener/WebSocketTopicListener.java @@ -0,0 +1,43 @@ +package com.ruoyi.common.websocket.listener; + +import cn.hutool.core.collection.CollUtil; +import com.ruoyi.common.websocket.utils.WebSocketUtils; +import com.ruoyi.common.websocket.holder.WebSocketSessionHolder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.Ordered; + +/** + * WebSocket 主题订阅监听器 + * + * @author zendwang + */ +@Slf4j +public class WebSocketTopicListener implements ApplicationRunner, Ordered { + + @Override + public void run(ApplicationArguments args) throws Exception { + WebSocketUtils.subscribeMessage((message) -> { + log.info("WebSocket主题订阅收到消息session keys={} message={}", message.getSessionKeys(), message.getMessage()); + // 如果key不为空就按照key发消息 如果为空就群发 + if (CollUtil.isNotEmpty(message.getSessionKeys())) { + message.getSessionKeys().forEach(key -> { + if (WebSocketSessionHolder.existSession(key)) { + WebSocketUtils.sendMessage(key, message.getMessage()); + } + }); + } else { + WebSocketSessionHolder.getSessionsAll().forEach(key -> { + WebSocketUtils.sendMessage(key, message.getMessage()); + }); + } + }); + log.info("初始化WebSocket主题订阅监听器成功"); + } + + @Override + public int getOrder() { + return -1; + } +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/utils/WebSocketUtils.java b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/utils/WebSocketUtils.java new file mode 100644 index 0000000..2f26c8a --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/java/com/ruoyi/common/websocket/utils/WebSocketUtils.java @@ -0,0 +1,110 @@ +package com.ruoyi.common.websocket.utils; + +import cn.hutool.core.collection.CollUtil; +import com.ruoyi.common.websocket.dto.WebSocketMessageDto; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import com.ruoyi.common.redis.utils.RedisUtils; +import com.ruoyi.common.websocket.holder.WebSocketSessionHolder; +import org.springframework.web.socket.PongMessage; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import static com.ruoyi.common.websocket.constant.WebSocketConstants.WEB_SOCKET_TOPIC; + +/** + * 工具类 + * + * @author zendwang + */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class WebSocketUtils { + + /** + * 发送消息 + * + * @param sessionKey session主键 一般为用户id + * @param message 消息文本 + */ + public static void sendMessage(Long sessionKey, String message) { + WebSocketSession session = WebSocketSessionHolder.getSessions(sessionKey); + sendMessage(session, message); + } + + /** + * 订阅消息 + * + * @param consumer 自定义处理 + */ + public static void subscribeMessage(Consumer consumer) { + RedisUtils.subscribe(WEB_SOCKET_TOPIC, WebSocketMessageDto.class, consumer); + } + + /** + * 发布订阅的消息 + * + * @param webSocketMessage 消息对象 + */ + public static void publishMessage(WebSocketMessageDto webSocketMessage) { + List unsentSessionKeys = new ArrayList<>(); + // 当前服务内session,直接发送消息 + for (Long sessionKey : webSocketMessage.getSessionKeys()) { + if (WebSocketSessionHolder.existSession(sessionKey)) { + WebSocketUtils.sendMessage(sessionKey, webSocketMessage.getMessage()); + continue; + } + unsentSessionKeys.add(sessionKey); + } + // 不在当前服务内session,发布订阅消息 + if (CollUtil.isNotEmpty(unsentSessionKeys)) { + WebSocketMessageDto broadcastMessage = new WebSocketMessageDto(); + broadcastMessage.setMessage(webSocketMessage.getMessage()); + broadcastMessage.setSessionKeys(unsentSessionKeys); + RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> { + log.info(" WebSocket发送主题订阅消息topic:{} session keys:{} message:{}", + WEB_SOCKET_TOPIC, unsentSessionKeys, webSocketMessage.getMessage()); + }); + } + } + + /** + * 发布订阅的消息(群发) + * + * @param message 消息内容 + */ + public static void publishAll(String message) { + WebSocketMessageDto broadcastMessage = new WebSocketMessageDto(); + broadcastMessage.setMessage(message); + RedisUtils.publish(WEB_SOCKET_TOPIC, broadcastMessage, consumer -> { + log.info("WebSocket发送主题订阅消息topic:{} message:{}", WEB_SOCKET_TOPIC, message); + }); + } + + public static void sendPongMessage(WebSocketSession session) { + sendMessage(session, new PongMessage()); + } + + public static void sendMessage(WebSocketSession session, String message) { + sendMessage(session, new TextMessage(message)); + } + + private static void sendMessage(WebSocketSession session, WebSocketMessage message) { + if (session == null || !session.isOpen()) { + log.warn("[send] session会话已经关闭"); + } else { + try { + session.sendMessage(message); + } catch (IOException e) { + log.error("[send] session({}) 发送消息({}) 异常", session, message, e); + } + } + } +} diff --git a/ruoyi-common/ruoyi-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..3a059fa --- /dev/null +++ b/ruoyi-common/ruoyi-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.ruoyi.common.websocket.config.WebSocketConfig