You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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配置:

  1. 安装依赖:
npm install @stomp/stompjs
  1. 修改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:

  1. 修改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("*"); // 根据实际环境设置允许的源
    }
}
  1. 创建自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 06:50:07