React+Vite应用无法与Spring Boot后端建立WebSocket连接
问题场景
React+Vite应用运行在localhost:5173,Spring Boot后端运行在localhost:5729。前端尝试连接后端WebSocket服务时失败,但Postman可正常连接该服务,且Spring Boot端无任何日志输出。
前端App.jsx代码
import { useState } from 'react' import './App.css' function App() { const [list, setList] = useState([]) var ws = new WebSocket("ws://localhost:5729/cp") ws.onmessage=(message)=>{console.log(message); setList([...list,message])}; return ( <ul> {list.map(element => { return (<li>element</li>); }) } </ul> ) } export default App
Spring Boot配置类代码
@Configuration @EnableWebSocket //@ServerEndpoint("/cp") public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new Handler(),"/cp"); } class Handler extends TextWebSocketHandler { private List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) { System.out.println("Session Added: "+session.getId()); sessions.add(session); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { System.out.println("Closed"); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message){ for(var t: sessions){ try { t.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } } }
前端控制台错误信息
App.jsx:7 WebSocket connection to 'ws://localhost:5729/cp' failed: App.jsx:7 WebSocket connection to 'ws://localhost:5729/cp' failed:
解决方案
1. 解决跨域问题
前端与后端端口不同属于跨域请求,Spring Boot的WebSocket配置需添加跨域支持,修改registerWebSocketHandlers方法:
@Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new Handler(), "/cp") .setAllowedOrigins("http://localhost:5173"); // 允许前端域名访问 }
若需临时允许所有域名可使用"*",但生产环境不建议这么做。
2. 修复前端状态更新与渲染问题
当前onmessage中捕获的list是闭包初始值,状态更新会有异常,同时渲染未显示实际内容,建议调整:
ws.onmessage=(message)=>{ console.log(message); setList(prevList => [...prevList, message.data]); // 用函数式更新获取最新状态,取message.data而非整个对象 };
渲染时添加key并显示实际内容:
{list.map((element, index) => { return (<li key={index}>{element}</li>); })}
3. 规范WebSocket实例生命周期
组件每次渲染都会创建新连接,建议用useEffect包裹避免重复创建,同时在组件卸载时关闭连接:
import { useState, useEffect } from 'react' import './App.css' function App() { const [list, setList] = useState([]) useEffect(() => { const ws = new WebSocket("ws://localhost:5729/cp") ws.onmessage=(message)=>{ console.log(message); setList(prevList => [...prevList, message.data]); }; return () => { ws.close(); }; }, []); // 空依赖确保只执行一次 return ( <ul> {list.map((element, index) => { return (<li key={index}>{element}</li>); })} </ul> ) } export default App
内容的提问来源于stack exchange,提问作者Thug Life
相关产品推荐
相关产品推荐

