React Native通过WebSocket发消息至Spring Boot无响应求助
React Native 向 Spring Boot WebSocket 发送消息无响应问题
我尝试通过WebSocket从React Native向Spring Boot发送字符串,但Spring Boot端无法显示消息。React Native已成功连接到ws://192.168.1.14:9091/audio,连接状态正常,且已发送字符串something。
React Native 代码
import React, { useEffect, useState } from 'react'; import { View, Text, ActivityIndicator } from 'react-native'; import { RTCView, mediaDevices } from 'react-native-webrtc'; const CameraScreen = () => { const [isLoading, setIsLoading] = useState(true); const [audioStream, setAudioStream] = useState(null); var ws = new WebSocket('ws://192.168.1.14:9091/audio'); useEffect(() => { Voip(); }, []); ws.onopen = () => { // connection opened console.log("opened!!"); ws.send('something'); // send a message }; ws.onerror = (error) => { console.error('WebSocket error:', error); }; async function Voip(){ try { const stream = await mediaDevices.getUserMedia({ audio: true, video: false }); setAudioStream(stream); // if (audioStream) { // console.log('Audio Stream:', audioStream); // } } catch (error) { console.error('Error getting user media:', error); } } return ( <View style={styles.container}> <Text>Audio Screen</Text> {audioStream && ( <RTCView streamURL={audioStream.toURL()} style={{ width: 200, height: 200 }} /> )} </View> ); }; export default CameraScreen; const styles = { container: { flex: 1, justifyContent: 'center', alignItems: 'center', gap: 20, backgroundColor: '#f2f2f2', }, };
Spring Boot WebSocket 配置类
package infili.findTeam.configuration; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/audio"); } }
Spring Boot 控制器
package infili.findTeam.controller; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.stereotype.Controller; @Controller public class WebSocketController { @MessageMapping("/audio") public void processMessage(String message) { // Your WebSocket message handling logic here System.out.println("message"); } }
Spring Boot 主类
package infili.findTeam; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @SpringBootApplication @EnableSwagger2 @EnableScheduling @EnableWebSocketMessageBroker @EnableJpaRepositories(basePackages = {"infili.findTeam.repositories"}) @ComponentScan(basePackages = { "infili.findTeam.configuration", "infili.findTeam.controller", "infili.findTeam.entity", "infili.findTeam.service", "infili.findTeam.util", "infili.findTeam.filters"}) public class findTeam { public static void main(String[] args) { SpringApplication.run(findTeam.class, args); } @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .paths(PathSelectors.any()) .paths(PathSelectors.regex("(?!/error).+")) .apis(RequestHandlerSelectors.any()) .build() .apiInfo(apiDetails()); } private ApiInfo apiDetails() { return new ApiInfoBuilder() .title("Find Team") .description("Utilise API services within MyCoach") .version("0.1") .build(); } }
问题原因与解决方法
核心问题:协议不匹配
Spring Boot配置使用的是STOMP协议(WebSocket的子协议),但React Native端用原生WebSocket协议直接发送文本,两者不兼容,导致Spring Boot无法解析消息并路由到@MessageMapping方法。
解决方式二选一:
方式1:React Native改用STOMP客户端发送消息
使用@stomp/stompjs适配Spring Boot的STOMP配置:
- 安装依赖:
npm install @stomp/stompjs
- 修改React Native的WebSocket逻辑:
import { Client } from '@stomp/stompjs'; const CameraScreen = () => { // 替换原WebSocket初始化代码 const client = new Client({ brokerURL: 'ws://192.168.1.14:9091/audio', onConnect: () => { console.log("STOMP连接成功"); // 消息需发送到/app/audio(配置前缀+映射路径) client.publish({ destination: '/app/audio', body: 'something' }); }, onStompError: (frame) => { console.error('STOMP错误:', frame.headers['message']); } }); useEffect(() => { Voip(); client.activate(); return () => client.deactivate(); // 组件卸载时断开连接 }, []); // 保留原Voip函数与渲染逻辑... };
方式2:Spring Boot改用原生WebSocket处理
如果不想用STOMP,修改配置为原生WebSocket:
- 修改WebSocketConfig类:
package infili.findTeam.configuration; 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; import infili.findTeam.handler.AudioWebSocketHandler; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new AudioWebSocketHandler(), "/audio") .setAllowedOrigins("*"); // 根据实际环境设置允许的源 } }
- 创建自定义WebSocket处理器:
package infili.findTeam.handler; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; public class AudioWebSocketHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); System.out.println("收到消息:" + payload); // 这里添加消息处理逻辑 } }
额外注意事项
- 确保Spring Boot的9091端口无防火墙/路由器拦截
- 真机测试时,React Native设备需与Spring Boot服务在同一局域网
- 原控制器中
System.out.println("message");只会打印固定字符串,建议改为System.out.println(message);查看实际消息内容
内容的提问来源于stack exchange,提问作者George Papadakis
相关产品推荐
相关产品推荐

