From 66b7e8c757fdcee71da5b8e7db052630aad9fe68 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Tue, 29 Jul 2025 17:14:16 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=99=E5=9D=97=E8=AF=B7=E6=B1=82=E9=83=BD?= =?UTF-8?q?=E4=BC=9A=E8=A2=AB=E9=87=8D=E5=AE=9A=E5=90=91=E5=88=B0=E7=99=BB?= =?UTF-8?q?=E9=99=86=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../websocket/WebSocketTestController.java | 71 +++- klp-admin/src/main/resources/application.yml | 5 + .../klp/framework/config/SaTokenConfig.java | 4 + .../framework/websocket/WebSocketUsers.java | 2 +- klp-ui/public/websocket-test.html | 305 +++++++++++++++++- 5 files changed, 381 insertions(+), 6 deletions(-) diff --git a/klp-admin/src/main/java/com/klp/web/controller/websocket/WebSocketTestController.java b/klp-admin/src/main/java/com/klp/web/controller/websocket/WebSocketTestController.java index 6e87c5bc..cd9baccb 100644 --- a/klp-admin/src/main/java/com/klp/web/controller/websocket/WebSocketTestController.java +++ b/klp-admin/src/main/java/com/klp/web/controller/websocket/WebSocketTestController.java @@ -1,14 +1,21 @@ package com.klp.web.controller.websocket; +import cn.dev33.satoken.annotation.SaIgnore; import com.klp.common.core.controller.BaseController; import com.klp.common.core.domain.R; +import com.klp.framework.websocket.WebSocketUsers; import org.springframework.web.bind.annotation.*; +import javax.websocket.Session; +import java.util.List; +import java.util.Map; + /** * WebSocket测试控制器 * * @author klp */ +@SaIgnore @RestController @RequestMapping("/websocket/test") public class WebSocketTestController extends BaseController { @@ -16,17 +23,75 @@ public class WebSocketTestController extends BaseController { /** * 测试WebSocket端点是否可用 */ + @SaIgnore @GetMapping("/status") public R getWebSocketStatus() { + System.out.println("=== WebSocket状态接口被调用 ==="); + System.out.println("=== 当前线程: " + Thread.currentThread().getName() + " ==="); + System.out.println("=== 请求路径: /websocket/test/status ==="); return R.ok("WebSocket端点可用,连接地址: ws://localhost:8080/websocket/message"); } /** * 获取当前连接数 */ + @SaIgnore @GetMapping("/connections") public R getConnectionCount() { - // 这里可以调用WebSocketUsers.getUsers().size()来获取实际连接数 - return R.ok(0); + try { + int count = WebSocketUsers.getUsers().size(); + return R.ok(count); + } catch (Exception e) { + return R.ok(0); + } } -} \ No newline at end of file + + /** + * 发送广播消息 + */ + @SaIgnore + @PostMapping("/broadcast") + public R sendBroadcast(@RequestParam String message) { + try { + WebSocketUsers.sendMessageToUsersByText("系统广播: " + message); + return R.ok("广播消息发送成功"); + } catch (Exception e) { + return R.fail("广播消息发送失败: " + e.getMessage()); + } + } + + /** + * 发送消息给指定用户 + */ + @SaIgnore + @PostMapping("/sendToUser") + public R sendToUser(@RequestParam String sessionId, @RequestParam String message) { + try { + Map users = WebSocketUsers.getUsers(); + Session session = users.get(sessionId); + if (session != null) { + WebSocketUsers.sendMessageToUserByText(session, "私信: " + message); + return R.ok("消息发送成功"); + } else { + return R.fail("用户不在线或会话ID无效"); + } + } catch (Exception e) { + return R.fail("消息发送失败: " + e.getMessage()); + } + } + + /** + * 获取所有在线用户会话ID + */ + @SaIgnore + @GetMapping("/users") + public R> getOnlineUsers() { + try { + Map users = WebSocketUsers.getUsers(); + List sessionIds = new java.util.ArrayList<>(users.keySet()); + return R.ok(sessionIds); + } catch (Exception e) { + return R.ok(new java.util.ArrayList<>()); + } + } +} diff --git a/klp-admin/src/main/resources/application.yml b/klp-admin/src/main/resources/application.yml index 3459d1f4..74ca42ab 100644 --- a/klp-admin/src/main/resources/application.yml +++ b/klp-admin/src/main/resources/application.yml @@ -143,6 +143,11 @@ security: # WebSocket路径 - /websocket/** - /wms/websocket/** + # WebSocket测试接口 + - /websocket/test/** + - /websocket/direct/** + # 测试接口 + - /test/** # MyBatisPlus配置 diff --git a/klp-framework/src/main/java/com/klp/framework/config/SaTokenConfig.java b/klp-framework/src/main/java/com/klp/framework/config/SaTokenConfig.java index 2277313c..501a5bd8 100644 --- a/klp-framework/src/main/java/com/klp/framework/config/SaTokenConfig.java +++ b/klp-framework/src/main/java/com/klp/framework/config/SaTokenConfig.java @@ -7,6 +7,7 @@ import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpInterface; import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.stp.StpUtil; +import java.util.Arrays; import com.klp.common.utils.spring.SpringUtils; import com.klp.framework.config.properties.SecurityProperties; import com.klp.framework.handler.AllUrlHandler; @@ -58,6 +59,9 @@ public class SaTokenConfig implements WebMvcConfigurer { })).addPathPatterns("/**") // 排除不需要拦截的路径 .excludePathPatterns(securityProperties.getExcludes()); + + // 添加调试日志 + log.info("Sa-Token拦截器配置完成,排除路径: {}", Arrays.toString(securityProperties.getExcludes())); } @Bean diff --git a/klp-framework/src/main/java/com/klp/framework/websocket/WebSocketUsers.java b/klp-framework/src/main/java/com/klp/framework/websocket/WebSocketUsers.java index 2007e60b..bc26f160 100644 --- a/klp-framework/src/main/java/com/klp/framework/websocket/WebSocketUsers.java +++ b/klp-framework/src/main/java/com/klp/framework/websocket/WebSocketUsers.java @@ -116,7 +116,7 @@ public class WebSocketUsers /** * 发送文本消息 * - * @param userName 自己的用户名 + * @param session 自己的用户名 * @param message 消息内容 */ public static void sendMessageToUserByText(Session session, String message) diff --git a/klp-ui/public/websocket-test.html b/klp-ui/public/websocket-test.html index e9b86390..9b0c42b0 100644 --- a/klp-ui/public/websocket-test.html +++ b/klp-ui/public/websocket-test.html @@ -97,6 +97,34 @@ .back-btn { margin-bottom: 20px; } + + .btn-warning { + background-color: #ffc107; + color: #212529; + } + + .btn-secondary { + background-color: #6c757d; + color: white; + } + + .btn-success { + background-color: #28a745; + color: white; + } + + select { + width: 100%; + padding: 8px; + border: 1px solid #ddd; + border-radius: 4px; + box-sizing: border-box; + } + + select:disabled { + background-color: #f8f9fa; + cursor: not-allowed; + } @@ -118,6 +146,34 @@ + + + +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ + +
+
+ + +
@@ -152,6 +208,9 @@ var joinBtn = document.getElementById('btn_join'); var exitBtn = document.getElementById('btn_exit'); var sendBtn = document.getElementById('btn_send'); + var broadcastBtn = document.getElementById('btn_broadcast'); + var getUsersBtn = document.getElementById('btn_get_users'); + var sendPrivateBtn = document.getElementById('btn_send_private'); if (connected) { statusDiv.textContent = '已连接'; @@ -159,12 +218,18 @@ joinBtn.disabled = true; exitBtn.disabled = false; sendBtn.disabled = false; + broadcastBtn.disabled = false; + getUsersBtn.disabled = false; + sendPrivateBtn.disabled = false; } else { statusDiv.textContent = '未连接'; statusDiv.className = 'status disconnected'; joinBtn.disabled = false; exitBtn.disabled = true; sendBtn.disabled = true; + broadcastBtn.disabled = true; + getUsersBtn.disabled = true; + sendPrivateBtn.disabled = true; } } @@ -230,10 +295,21 @@ addLog('正在测试服务器状态...'); fetch('/websocket/test/status') .then(response => { + addLog('服务器响应状态: ' + response.status + ' ' + response.statusText); if (response.ok) { - return response.json(); + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (e) { + addLog('响应内容不是JSON格式: ' + text.substring(0, 200)); + throw new Error('响应格式错误'); + } + }); } else { - throw new Error('服务器响应错误: ' + response.status); + return response.text().then(text => { + addLog('错误响应内容: ' + text.substring(0, 200)); + throw new Error('服务器响应错误: ' + response.status); + }); } }) .then(data => { @@ -244,6 +320,231 @@ }); }); + // 直接测试接口 + $('#btn_test_direct').click(function() { + addLog('=== 直接测试接口开始 ==='); + + // 测试1: 直接访问接口 + addLog('测试1: 直接访问 /websocket/test/status'); + fetch('/websocket/test/status', { + method: 'GET', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + } + }).then(response => { + addLog('响应状态: ' + response.status + ' ' + response.statusText); + addLog('响应头: ' + JSON.stringify(Object.fromEntries(response.headers.entries()))); + return response.text(); + }).then(text => { + addLog('响应内容: ' + text.substring(0, 500)); + if (text.includes('')) { + addLog('❌ 返回了HTML页面,说明被重定向到登录页面'); + } else { + addLog('✅ 返回了非HTML内容'); + } + }).catch(error => { + addLog('请求失败: ' + error.message); + }); + + // 测试2: 测试简单控制器 + setTimeout(() => { + addLog('测试2: 测试 /test/hello(简单控制器)'); + fetch('/test/hello', { + method: 'GET' + }).then(response => { + addLog('简单控制器响应状态: ' + response.status + ' ' + response.statusText); + return response.text(); + }).then(text => { + addLog('简单控制器响应内容: ' + text.substring(0, 200)); + if (text.includes('')) { + addLog('❌ 简单控制器也返回了HTML页面'); + } else { + addLog('✅ 简单控制器返回了非HTML内容'); + } + }).catch(error => { + addLog('简单控制器请求失败: ' + error.message); + }); + }, 1000); + + // 测试3: 测试actuator接口(应该工作) + setTimeout(() => { + addLog('测试3: 测试 /actuator/health(应该工作)'); + fetch('/actuator/health', { + method: 'GET' + }).then(response => { + addLog('Actuator响应状态: ' + response.status + ' ' + response.statusText); + return response.text(); + }).then(text => { + addLog('Actuator响应内容: ' + text.substring(0, 200)); + }).catch(error => { + addLog('Actuator请求失败: ' + error.message); + }); + }, 2000); + + addLog('=== 直接测试接口结束 ==='); + }); + + // 测试连接数 + $('#btn_test_data').click(function() { + addLog('正在获取连接数...'); + fetch('/websocket/test/connections', { + method: 'GET' + }).then(response => { + addLog('连接数响应状态: ' + response.status + ' ' + response.statusText); + if (response.ok) { + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (e) { + addLog('连接数响应内容不是JSON格式: ' + text.substring(0, 200)); + throw new Error('响应格式错误'); + } + }); + } else { + return response.text().then(text => { + addLog('连接数错误响应内容: ' + text.substring(0, 200)); + throw new Error('获取连接数失败: ' + response.status); + }); + } + }).then(data => { + addLog('当前连接数: ' + data.data); + }).catch(error => { + addLog('获取连接数失败: ' + error.message); + }); + }); + + // 发送广播消息 + $('#btn_broadcast').click(function() { + var message = $('#broadcast_message').val(); + if (!message.trim()) { + addLog('请输入广播消息内容'); + return; + } + + addLog('正在发送广播消息: ' + message); + var formData = new FormData(); + formData.append('message', message); + + fetch('/websocket/test/broadcast', { + method: 'POST', + body: formData + }).then(response => { + addLog('广播响应状态: ' + response.status + ' ' + response.statusText); + if (response.ok) { + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (e) { + addLog('广播响应内容不是JSON格式: ' + text.substring(0, 200)); + throw new Error('响应格式错误'); + } + }); + } else { + return response.text().then(text => { + addLog('广播错误响应内容: ' + text.substring(0, 200)); + throw new Error('广播发送失败: ' + response.status); + }); + } + }).then(data => { + addLog('广播结果: ' + data.msg); + $('#broadcast_message').val(''); + }).catch(error => { + addLog('广播发送失败: ' + error.message); + }); + }); + + // 获取在线用户 + $('#btn_get_users').click(function() { + addLog('正在获取在线用户...'); + fetch('/websocket/test/users', { + method: 'GET' + }).then(response => { + addLog('用户列表响应状态: ' + response.status + ' ' + response.statusText); + if (response.ok) { + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (e) { + addLog('用户列表响应内容不是JSON格式: ' + text.substring(0, 200)); + throw new Error('响应格式错误'); + } + }); + } else { + return response.text().then(text => { + addLog('用户列表错误响应内容: ' + text.substring(0, 200)); + throw new Error('获取用户列表失败: ' + response.status); + }); + } + }).then(data => { + addLog('在线用户数量: ' + data.data.length); + updateUserSelect(data.data); + }).catch(error => { + addLog('获取用户列表失败: ' + error.message); + }); + }); + + // 发送私信 + $('#btn_send_private').click(function() { + var sessionId = $('#user_session').val(); + var message = $('#private_message').val(); + + if (!sessionId) { + addLog('请选择要发送的用户'); + return; + } + if (!message.trim()) { + addLog('请输入私信内容'); + return; + } + + addLog('正在发送私信给用户 ' + sessionId + ': ' + message); + var formData = new FormData(); + formData.append('sessionId', sessionId); + formData.append('message', message); + + fetch('/websocket/test/sendToUser', { + method: 'POST', + body: formData + }).then(response => { + addLog('私信响应状态: ' + response.status + ' ' + response.statusText); + if (response.ok) { + return response.text().then(text => { + try { + return JSON.parse(text); + } catch (e) { + addLog('私信响应内容不是JSON格式: ' + text.substring(0, 200)); + throw new Error('响应格式错误'); + } + }); + } else { + return response.text().then(text => { + addLog('私信错误响应内容: ' + text.substring(0, 200)); + throw new Error('私信发送失败: ' + response.status); + }); + } + }).then(data => { + addLog('私信结果: ' + data.msg); + $('#private_message').val(''); + }).catch(error => { + addLog('私信发送失败: ' + error.message); + }); + }); + + // 更新用户选择下拉框 + function updateUserSelect(users) { + var select = $('#user_session'); + select.empty(); + select.append(''); + + users.forEach(function(user) { + select.append(''); + }); + + select.prop('disabled', false); + addLog('用户列表已更新'); + } + // 回车发送消息 $('#message').keypress(function(e) { if (e.which == 13 && !e.shiftKey) {