使用Java接口调用websocket_java调用websocket接口
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
方法并配置二进制缓冲区大小