From fbb38ffdcfba9982b5f78869ae746cd116e9d883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E5=87=A4=E5=90=89?= Date: Thu, 31 Jul 2025 17:14:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:ws=E9=93=BE=E6=8E=A5=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E5=90=8E=E4=B8=BB=E5=8A=A8=E6=8E=A8=E9=80=81=E4=B8=80=E6=AC=A1?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/websocket/server/MyWebSocketHandler.java | 41 ++++++++++++++ .../app/websocket/server/WebSocketConfig.java | 24 +++++++++ .../websocket/server/WebSocketConnectedEvent.java | 17 ++++++ .../websocket/server/WebSocketEventListener.java | 27 ++++++++++ .../app/websocket/server/WebSocketSender.java | 25 ++++----- .../app/websocket/server/WebSocketServer.java | 51 ------------------ .../websocket/server/WebSocketServerConfig.java | 14 ----- .../websocket/server/WebSocketSessionManager.java | 63 ++++++++++++++++++++++ .../app/websocket/server/WebsocketMsg.java | 21 ++++++++ .../app/websocket/server/WebsocketResult.java | 21 -------- 10 files changed, 203 insertions(+), 101 deletions(-) create mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/MyWebSocketHandler.java create mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConfig.java create mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConnectedEvent.java create mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketEventListener.java delete mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServer.java delete mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServerConfig.java create mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSessionManager.java create mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketMsg.java delete mode 100644 src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketResult.java diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/MyWebSocketHandler.java b/src/main/java/com/iflytop/handacid/app/websocket/server/MyWebSocketHandler.java new file mode 100644 index 0000000..8a7be45 --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/websocket/server/MyWebSocketHandler.java @@ -0,0 +1,41 @@ +package com.iflytop.handacid.app.websocket.server; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +@Slf4j +@Component +public class MyWebSocketHandler extends TextWebSocketHandler { + + private final WebSocketSessionManager sessionManager; + private final ApplicationEventPublisher eventPublisher; + + public MyWebSocketHandler(WebSocketSessionManager sessionManager, ApplicationEventPublisher eventPublisher) { + this.sessionManager = sessionManager; + this.eventPublisher = eventPublisher; + } + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + sessionManager.add(session); + eventPublisher.publishEvent(new WebSocketConnectedEvent(this, session)); + } + + @Override + public void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) throws Exception { + // 从管理器移除 + sessionManager.remove(session); + super.afterConnectionClosed(session, status); + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + // 如果需要,也可以在这里处理消息 + log.info("收到消息,sessionId={},内容={}", session.getId(), message.getPayload()); + + } +} \ No newline at end of file diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConfig.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConfig.java new file mode 100644 index 0000000..35f60dd --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConfig.java @@ -0,0 +1,24 @@ +package com.iflytop.handacid.app.websocket.server; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +@Configuration +@EnableWebSocket +public class WebSocketConfig implements WebSocketConfigurer { + + private final MyWebSocketHandler myWebSocketHandler; + + public WebSocketConfig(MyWebSocketHandler myWebSocketHandler) { + this.myWebSocketHandler = myWebSocketHandler; + } + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(myWebSocketHandler, "/ws") + .setAllowedOrigins("*") // 根据需要限制 + .addInterceptors(new org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor()); + } +} \ No newline at end of file diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConnectedEvent.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConnectedEvent.java new file mode 100644 index 0000000..d466960 --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketConnectedEvent.java @@ -0,0 +1,17 @@ +package com.iflytop.handacid.app.websocket.server; + + +import lombok.Getter; +import org.springframework.context.ApplicationEvent; +import org.springframework.web.socket.WebSocketSession; + +@Getter +public class WebSocketConnectedEvent extends ApplicationEvent { + private final WebSocketSession session; + + public WebSocketConnectedEvent(Object source, WebSocketSession session) { + super(source); + this.session = session; + } + +} \ No newline at end of file diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketEventListener.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketEventListener.java new file mode 100644 index 0000000..54cca33 --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketEventListener.java @@ -0,0 +1,27 @@ +package com.iflytop.handacid.app.websocket.server; + +import com.iflytop.handacid.app.core.state.DeviceState; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.io.IOException; + +@Slf4j +@Component +@RequiredArgsConstructor +public class WebSocketEventListener { + private final WebSocketSender webSocketSender; + private final DeviceState deviceState; + + @EventListener + public void handleWebSocketConnected(WebSocketConnectedEvent event) throws IOException { + WebSocketSession session = event.getSession(); + log.info("监听到新的 WS 连接,sessionId={}", session.getId()); + session.sendMessage(new TextMessage("链接成功")); + webSocketSender.push(WebSocketMessageType.STATUS, deviceState.toJSON()); + } +} \ No newline at end of file diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSender.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSender.java index 675508a..e5528bd 100644 --- a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSender.java +++ b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSender.java @@ -1,6 +1,7 @@ package com.iflytop.handacid.app.websocket.server; import cn.hutool.json.JSONUtil; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; @@ -11,14 +12,18 @@ import java.time.format.DateTimeFormatter; @Slf4j @Component +@RequiredArgsConstructor public class WebSocketSender { + private final WebSocketSessionManager sessionManager; public void push(String type, Object data) { - WebsocketResult websocketResult = new WebsocketResult(); - websocketResult.setType(type); - websocketResult.setData(data); - websocketResult.setTimestamp(Instant.now().toEpochMilli()); - WebSocketServer.sendMessageToClients(JSONUtil.toJsonStr(websocketResult)); + WebsocketMsg msg = new WebsocketMsg(); + msg.setType(type); + msg.setData(data); + msg.setTimestamp(Instant.now().toEpochMilli()); + + String json = JSONUtil.toJsonStr(msg); + sessionManager.broadcast(json); } @@ -26,16 +31,6 @@ public class WebSocketSender { push(WebSocketMessageType.CMD_DEBUG, data); } - public void pushLog(String code, String type, String content) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - String formattedDate = LocalDateTime.now().format(formatter); - WebsocketResult websocketResult = new WebsocketResult(); - websocketResult.setType(WebSocketMessageType.LOG); - websocketResult.setData(formattedDate + "模块" + StringUtils.substring(code, code.length() - 1) + type + content); - websocketResult.setTimestamp(Instant.now().toEpochMilli()); - WebSocketServer.sendMessageToClients(JSONUtil.toJsonStr(websocketResult)); - } - public void pushCMDResponse(Object data) { push(WebSocketMessageType.CMD_RESPONSE, data); } diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServer.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServer.java deleted file mode 100644 index 816b56f..0000000 --- a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServer.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.iflytop.handacid.app.websocket.server; - -import jakarta.websocket.*; -import jakarta.websocket.server.ServerEndpoint; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -@Slf4j -@ServerEndpoint("/ws") -@Component -public class WebSocketServer { - private static final Set sessions = Collections.synchronizedSet(new HashSet<>()); - - public static void sendMessageToClients(String message) { - synchronized (sessions) { - for (Session session : sessions) { - try { - session.getBasicRemote().sendText(message); - } catch (Exception e) { - log.error("WS发送给客户端失败 sessionId={}", session.getId(), e); - } - } - } - } - - @OnOpen - public void onOpen(Session session) { - sessions.add(session); - log.info("新连接加入,sessionId={}", session.getId()); - } - - @OnMessage - public void onMessage(String message, Session session) { - log.info("收到消息 sessionId={},内容:{}", session.getId(), message); - } - - @OnClose - public void onClose(Session session) { - sessions.remove(session); - log.info("连接已关闭,sessionId={}", session.getId()); - } - - @OnError - public void onError(Session session, Throwable error) { - log.error("发生错误,sessionId={}", session.getId(), error); - } -} diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServerConfig.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServerConfig.java deleted file mode 100644 index 60233f2..0000000 --- a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketServerConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.iflytop.handacid.app.websocket.server; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.socket.server.standard.ServerEndpointExporter; - -@Configuration -public class WebSocketServerConfig { - - @Bean - public ServerEndpointExporter serverEndpointExporter() { - return new ServerEndpointExporter(); - } -} diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSessionManager.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSessionManager.java new file mode 100644 index 0000000..e873fc8 --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/websocket/server/WebSocketSessionManager.java @@ -0,0 +1,63 @@ +package com.iflytop.handacid.app.websocket.server; + +import org.springframework.stereotype.Component; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** + * 统一管理所有 WebSocketSession + */ +@Component +public class WebSocketSessionManager { + + private final Set sessions = Collections.synchronizedSet(new HashSet<>()); + + /** + * 连接建立时调用 + */ + public void add(WebSocketSession session) { + sessions.add(session); + } + + /** + * 连接关闭时调用 + */ + public void remove(WebSocketSession session) { + sessions.remove(session); + } + + /** + * 广播所有在线客户端 + */ + public void broadcast(String payload) { + synchronized (sessions) { + for (WebSocketSession session : sessions) { + if (session.isOpen()) { + try { + session.sendMessage(new TextMessage(payload)); + } catch (IOException e) { + // log 或者移除无效 session + } + } + } + } + } + + /** + * 定向给某个 session 发消息 + */ + public void sendTo(WebSocketSession session, String payload) { + if (session.isOpen()) { + try { + session.sendMessage(new TextMessage(payload)); + } catch (IOException e) { + // log + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketMsg.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketMsg.java new file mode 100644 index 0000000..ca5031e --- /dev/null +++ b/src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketMsg.java @@ -0,0 +1,21 @@ +package com.iflytop.handacid.app.websocket.server; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class WebsocketMsg { + /** + * 推送类型(指令 cmd,报警 warn ,状态 status) + */ + @Schema(description = "推送类型(指令 cmd,报警 warn ,状态 status)") + private String type; + /** + * 执行结果 + */ + @Schema(description = "推送数据") + private Object data; + + @Schema(description = "推送时间戳") + private Long timestamp; +} \ No newline at end of file diff --git a/src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketResult.java b/src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketResult.java deleted file mode 100644 index 3963ff3..0000000 --- a/src/main/java/com/iflytop/handacid/app/websocket/server/WebsocketResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.iflytop.handacid.app.websocket.server; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Data -public class WebsocketResult { - /** - * 推送类型(指令 cmd,报警 warn ,状态 status) - */ - @Schema(description = "推送类型(指令 cmd,报警 warn ,状态 status)") - private String type; - /** - * 执行结果 - */ - @Schema(description = "推送数据") - private Object data; - - @Schema(description = "推送时间戳") - private Long timestamp; -} \ No newline at end of file