WebSocket 接口调用指南
概述
本文档提供通过 RESTful 接口调用 WebSocket 服务的完整解决方案,包含接口定义、实现逻辑、配置说明及注意事项。
快速开始
1.接口调用示例
POST /getWebSocketData
请求参数:
- data: 需要发送的文本数据
- url: WebSocket 服务地址(ws:// 或 wss:// 开头)
响应示例:
{
"code": 200,
"message": "success",
"data": { /* 处理后的JSON数据 */ }
}
2. 前置条件
- Spring Boot 2.x+
- 添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
代码详解
1. Controller 层
@PostMapping("/getWebSocketData")
@ApiOperation("根据路径参数获取ws数据")
public Result connectWS(
@RequestParam String data,
@RequestParam String url) {
try {
String result = envResultService.connectWebSocket(data, url);
//处理返回结果
JSONObject jsonObject = processData(result);
return Result.success(jsonObject);
} catch (Exception e) {
return Result.error("WebSocket连接失败: " + e.getMessage());
}
}
- 参数说明:
data
: 要发送的 WebSocket 消息内容url
: 目标 WebSocket 服务地址
- 特性:
- 统一异常处理
- 返回结果标准化处理
2. 服务实现层
@Override
public String connectWebSocket(String data, String url) {
CompletableFuture<String> responseFuture = new CompletableFuture<>();
StandardWebSocketClient client = new StandardWebSocketClient();
// 使用反射设置缓冲区大小
try {
Field containerField = StandardWebSocketClient.class.getDeclaredField("webSocketContainer");
containerField.setAccessible(true); // 允许访问私有字段
WebSocketContainer container = (WebSocketContainer) containerField.get(client);
// 设置缓冲区大小
container.setDefaultMaxTextMessageBufferSize(bufferConfig.getMaxTextMessageSize());
container.setDefaultMaxBinaryMessageBufferSize(bufferConfig.getMaxBinaryMessageSize());
} catch (Exception e) {
log.error("无法设置缓冲区大小: {}", e.getMessage());
}
WebSocketHandler handler = new AbstractWebSocketHandler() {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
log.info("WebSocket 连接已建立: {}", session.getId());
session.sendMessage(new TextMessage(data));
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
log.info("收到 WebSocket 响应: {}", message.getPayload());
responseFuture.complete(message.getPayload());
try {
session.close();
} catch (IOException e) {
log.error("关闭 WebSocket 会话时出错", e);
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
log.error("WebSocket 传输错误", exception);
responseFuture.completeExceptionally(exception);
}
};
ListenableFuture<WebSocketSession> handshakeFuture = client.doHandshake(handler, url);
handshakeFuture.addCallback(
session -> CompletableFuture.runAsync(() -> {
log.info("WebSocket 握手成功: {}", session.getId());
}, executorService),
ex -> CompletableFuture.runAsync(() -> {
log.error("WebSocket 握手失败", ex);
responseFuture.completeExceptionally(ex);
}, executorService)
);
try {
return responseFuture.get(60, TimeUnit.SECONDS);
} catch (TimeoutException e) {
log.error("等待 WebSocket 响应超时", e);
throw new RuntimeException("等待响应超时");
} catch (InterruptedException | ExecutionException e) {
log.error("请求中断或执行异常", e);
throw new RuntimeException("内部错误");
}
}
@PreDestroy
public void destroy() {
if (!executorService.isShutdown()) {
executorService.shutdown();
}
}
关键点:
- 使用
CompletableFuture
实现异步响应处理 - 反射修改 WebSocket 缓冲区大小(需处理安全检查)
- 60秒超时控制机制
- 自动关闭连接设计
3. WebSocket 配置类
@Configuration
@ConfigurationProperties(prefix = "websocket.buffer")
public class WebSocketBufferConfig {
private int maxTextMessageSize; // 文本消息最大尺寸
private int maxBinaryMessageSize; // 二进制消息最大尺寸
// Getter/Setter 省略
}
配置说明
application.yml
websocket:
buffer:
max-text-message-size: 104857600 # 100MB
max-binary-message-size: 104857600 # 100MB
参数说明:
max-text-message-size
: 文本消息缓冲区最大值max-binary-message-size
: 二进制消息缓冲区最大值
注意事项
- 安全警告:
- 反射修改私有字段
webSocketContainer
可能带来兼容性问题 - 生产环境建议通过正规方式配置 WebSocketContainer
- 反射修改私有字段
- 性能建议:
- 根据实际需求调整缓冲区大小
- 超时时间(60s)可根据网络状况优化
- 异常处理:
- 捕获
TimeoutException
防止线程阻塞 - 使用
@PreDestroy
确保优雅关闭线程池
- 捕获
- 使用限制:
- 仅支持单次请求-响应模式
- 不支持长连接保持
常见问题
Q1: 出现 403 Forbidden
错误
A: 检查目标 WebSocket 服务的跨域配置
Q2: 缓冲区设置不生效
A: 确保配置前缀正确,检查容器是否被其他配置覆盖
Q3: 收到消息不完整
A: 检查缓冲区大小是否足够,适当增加 max-text-message-size
Q4: 如何支持二进制消息?
A: 重写 handleBinaryMessage
方法并配置二进制缓冲区大小