package com.ruoyi.web.controller.webSocket;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import lombok.extern.slf4j.Slf4j;
|
import org.junit.Test;
|
import org.springframework.boot.test.context.SpringBootTest;
|
|
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.TimeUnit;
|
|
/**
|
* WebSocket客户端测试类
|
* 演示如何连接WebSocket服务端并进行认证
|
*/
|
@SpringBootTest
|
@Slf4j
|
public class WebSocketClientTest {
|
|
private static final String WEBSOCKET_URL = "ws://127.0.0.1:8888/hello";
|
private static final String TEST_USER_ID = "1964941649976532994";
|
private static final String TEST_TOKEN = "eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2FwcGxldF9rZXkiOiJhMzkyMTdmZS1hZmRiLTQ1YTAtYjkwMy01MGViNjc4ZGJlNzAifQ.SaLnyIsAQ9lnSivaXPaO71gReSmx-R_tjrS3auKJqbXKe2SiLr7MZiNetdjmwvE7HSzjxs1yTqVW9mXGcAuWHw";
|
|
/**
|
* 测试WebSocket连接和认证
|
*/
|
@Test
|
public void testWebSocketConnection() throws Exception {
|
CountDownLatch latch = new CountDownLatch(1);
|
|
// 创建WebSocket客户端
|
SimpleWebSocketClient client = new SimpleWebSocketClient(WEBSOCKET_URL, new WebSocketClient.MessageHandler() {
|
@Override
|
public void onOpen() {
|
log.info("WebSocket连接已建立");
|
// 发送认证消息
|
sendAuthMessage();
|
}
|
|
@Override
|
public void onMessage(String message) {
|
log.info("收到服务器消息: {}", message);
|
try {
|
JSONObject messageObj = JSON.parseObject(message);
|
String messageType = messageObj.getString("type");
|
|
switch (messageType) {
|
case "auth_success":
|
log.info("认证成功: {}", messageObj.getString("message"));
|
// 认证成功后发送业务消息
|
sendBusinessMessage();
|
break;
|
case "auth_failed":
|
log.error("认证失败: {}", messageObj.getString("message"));
|
break;
|
case "pong":
|
log.info("收到心跳响应");
|
break;
|
case "message_response":
|
log.info("收到业务消息响应: {}", messageObj.getString("originalMessage"));
|
break;
|
default:
|
log.info("收到其他消息: {}", message);
|
}
|
} catch (Exception e) {
|
log.error("解析消息失败: {}", e.getMessage());
|
}
|
}
|
|
@Override
|
public void onClose(int code, String reason) {
|
log.info("WebSocket连接已关闭: code={}, reason={}", code, reason);
|
latch.countDown();
|
}
|
|
@Override
|
public void onError(Exception e) {
|
log.error("WebSocket连接错误: {}", e.getMessage(), e);
|
latch.countDown();
|
}
|
});
|
|
// 连接WebSocket
|
client.connect();
|
|
// 等待连接关闭
|
latch.await(30, TimeUnit.SECONDS);
|
|
// 关闭连接
|
client.close();
|
}
|
|
/**
|
* 测试无Token认证
|
*/
|
@Test
|
public void testWebSocketConnectionWithoutToken() throws Exception {
|
CountDownLatch latch = new CountDownLatch(1);
|
|
SimpleWebSocketClient client = new SimpleWebSocketClient(WEBSOCKET_URL, new WebSocketClient.MessageHandler() {
|
@Override
|
public void onOpen() {
|
log.info("WebSocket连接已建立(无Token)");
|
sendAuthMessageWithoutToken();
|
}
|
|
@Override
|
public void onMessage(String message) {
|
log.info("收到服务器消息: {}", message);
|
handleMessage(message);
|
}
|
|
@Override
|
public void onClose(int code, String reason) {
|
log.info("WebSocket连接已关闭: code={}, reason={}", code, reason);
|
latch.countDown();
|
}
|
|
@Override
|
public void onError(Exception e) {
|
log.error("WebSocket连接错误: {}", e.getMessage(), e);
|
latch.countDown();
|
}
|
});
|
|
client.connect();
|
latch.await(10, TimeUnit.SECONDS);
|
client.close();
|
}
|
|
/**
|
* 测试心跳功能
|
*/
|
@Test
|
public void testWebSocketHeartbeat() throws Exception {
|
CountDownLatch latch = new CountDownLatch(1);
|
|
SimpleWebSocketClient client = new SimpleWebSocketClient(WEBSOCKET_URL, new WebSocketClient.MessageHandler() {
|
@Override
|
public void onOpen() {
|
log.info("WebSocket连接已建立");
|
sendAuthMessage();
|
}
|
|
@Override
|
public void onMessage(String message) {
|
log.info("收到服务器消息: {}", message);
|
|
try {
|
JSONObject messageObj = JSON.parseObject(message);
|
String messageType = messageObj.getString("type");
|
|
if ("auth_success".equals(messageType)) {
|
log.info("认证成功,开始发送心跳");
|
// 认证成功后开始发送心跳
|
startHeartbeat();
|
} else if ("pong".equals(messageType)) {
|
log.info("收到心跳响应");
|
}
|
} catch (Exception e) {
|
log.error("解析消息失败: {}", e.getMessage());
|
}
|
}
|
|
@Override
|
public void onClose(int code, String reason) {
|
log.info("WebSocket连接已关闭: code={}, reason={}", code, reason);
|
latch.countDown();
|
}
|
|
@Override
|
public void onError(Exception e) {
|
log.error("WebSocket连接错误: {}", e.getMessage(), e);
|
latch.countDown();
|
}
|
});
|
|
client.connect();
|
latch.await(30, TimeUnit.SECONDS);
|
client.close();
|
}
|
|
/**
|
* 发送认证消息
|
*/
|
private void sendAuthMessage() {
|
JSONObject authMessage = new JSONObject();
|
authMessage.put("type", "auth");
|
authMessage.put("appUserId", TEST_USER_ID);
|
authMessage.put("token", TEST_TOKEN);
|
|
|
String message = authMessage.toJSONString();
|
log.info("发送认证消息: {}", message);
|
// 这里需要实际的WebSocket客户端实现
|
}
|
|
public static void main(String[] args) {
|
// 发送认证消息: {"deviceType":"test","type":"auth","appUserId":"1964941649976532994","deviceId":"test-device-1761294213830","token":"eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2FwcGxldF9rZXkiOiJhMzkyMTdmZS1hZmRiLTQ1YTAtYjkwMy01MGViNjc4ZGJlNzAifQ.SaLnyIsAQ9lnSivaXPaO71gReSmx-R_tjrS3auKJqbXKe2SiLr7MZiNetdjmwvE7HSzjxs1yTqVW9mXGcAuWHw"}
|
// 发送认证消息: {"type":"auth","appUserId":"1964941649976532994","token":"eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2FwcGxldF9rZXkiOiJhMzkyMTdmZS1hZmRiLTQ1YTAtYjkwMy01MGViNjc4ZGJlNzAifQ.SaLnyIsAQ9lnSivaXPaO71gReSmx-R_tjrS3auKJqbXKe2SiLr7MZiNetdjmwvE7HSzjxs1yTqVW9mXGcAuWHw"}
|
|
// 发送心跳消息: {"type":"ping","timestamp":1761294280878}
|
|
// 发送业务消息: {"type":"business","content":"这是一条测试业务消息","timestamp":1761294280878}
|
JSONObject businessMessage = new JSONObject();
|
businessMessage.put("type", "mission_push");
|
businessMessage.put("content", "{\"missionId\":\"1976542839650725890\"}");
|
businessMessage.put("timestamp", System.currentTimeMillis());
|
|
String message = businessMessage.toJSONString();
|
log.info("发送业务消息: {}", message);
|
}
|
|
/**
|
* 发送无Token认证消息
|
*/
|
private void sendAuthMessageWithoutToken() {
|
JSONObject authMessage = new JSONObject();
|
authMessage.put("type", "auth");
|
authMessage.put("appUserId", TEST_USER_ID);
|
|
String message = authMessage.toJSONString();
|
log.info("发送无Token认证消息: {}", message);
|
}
|
|
/**
|
* 发送业务消息
|
*/
|
private void sendBusinessMessage() {
|
JSONObject businessMessage = new JSONObject();
|
businessMessage.put("type", "mission_push");
|
businessMessage.put("content", "{\"missionId\":\"1976542839650725890\"}");
|
businessMessage.put("timestamp", System.currentTimeMillis());
|
|
String message = businessMessage.toJSONString();
|
log.info("发送业务消息: {}", message);
|
}
|
|
/**
|
* 发送心跳消息
|
*/
|
private void sendPingMessage() {
|
JSONObject pingMessage = new JSONObject();
|
pingMessage.put("type", "ping");
|
pingMessage.put("timestamp", System.currentTimeMillis());
|
|
String message = pingMessage.toJSONString();
|
log.info("发送心跳消息: {}", message);
|
}
|
|
/**
|
* 开始心跳
|
*/
|
private void startHeartbeat() {
|
// 每5秒发送一次心跳
|
new Thread(() -> {
|
try {
|
for (int i = 0; i < 6; i++) {
|
Thread.sleep(5000);
|
sendPingMessage();
|
}
|
} catch (InterruptedException e) {
|
Thread.currentThread().interrupt();
|
}
|
}).start();
|
}
|
|
/**
|
* 处理服务器消息
|
*/
|
private void handleMessage(String message) {
|
try {
|
JSONObject messageObj = JSON.parseObject(message);
|
String messageType = messageObj.getString("type");
|
|
switch (messageType) {
|
case "auth_success":
|
log.info("认证成功: {}", messageObj.getString("message"));
|
break;
|
case "auth_failed":
|
log.error("认证失败: {}", messageObj.getString("message"));
|
break;
|
case "pong":
|
log.info("收到心跳响应");
|
break;
|
case "message_response":
|
log.info("收到业务消息响应");
|
break;
|
case "auth_required":
|
log.warn("需要重新认证: {}", messageObj.getString("message"));
|
break;
|
default:
|
log.info("收到其他消息: {}", message);
|
}
|
} catch (Exception e) {
|
log.error("解析消息失败: {}", e.getMessage());
|
}
|
}
|
|
/**
|
* WebSocket客户端接口
|
*/
|
public interface WebSocketClient {
|
|
void connect() throws Exception;
|
|
void send(String message);
|
|
void close();
|
|
interface MessageHandler {
|
void onOpen();
|
void onMessage(String message);
|
void onClose(int code, String reason);
|
void onError(Exception e);
|
}
|
}
|
}
|