Spring Boot WebSocket按身份发消息遇阻,convertAndSend消息前端无法接收
我用Spring Boot构建了一个Java应用,搭配浏览器端的简单JavaScript应用。目前能实现给所有用户广播消息,但想根据用户身份给不同用户发送消息时遇到了问题。我是WebSocket和JavaScript新手,查了大量文章仍未找到问题所在,希望能得到提示!
我尝试用messageTemplate.convertAndSend()方法给指定用户发消息,但现在连广播消息都出现异常:浏览器能接收login方法中if代码块返回的GreetingWS对象,却无法接收start方法里通过messageTemplate.convertAndSend("/topic/greetings", "Let's play!");发送的消息。
Java控制器代码
@Controller public class GreetingWSController { private SimpMessagingTemplate messageTemplate; public GreetingWSController(SimpMessagingTemplate template) { this.messageTemplate = template; } @MessageMapping("/login") @SendTo("/topic/greetings") public GreetingWS login(HelloMessage message) throws Exception { if (...) { System.out.println("A player has logged in."); return new GreetingWS("Welcome! You are the " + HtmlUtils.htmlEscape(order.toString()) + "th user."); } else { return start(); } } public void start() { messageTemplate.convertAndSend("/topic/greetings", "Let's play!"); } }
WebSocket配置代码
@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("/gs-guide-websocket"); } }
JavaScript客户端代码
const stompClient = new StompJs.Client({ brokerURL: 'ws://localhost:8080/gs-guide-websocket' }); stompClient.onConnect = (frame) => { setConnected(true); console.log('Connected: ' + frame); stompClient.subscribe('/topic/greetings', (greeting) => { showGreeting(JSON.parse(greeting.body).content); }); }; function setConnected(connected) { $("#connect").prop("disabled", connected); if (connected) { $("#conversation").show(); } else { $("#conversation").hide(); } $("#greetings").html(""); } function connect() { stompClient.activate(); } function showGreeting(message) { $("#greetings").append("<tr><td>" + message + "</td></tr>"); } $(function () { $("form").on('submit', (e) => e.preventDefault()); $( "#connect" ).click(() => connect()); });
问题排查与解决提示
数据格式不匹配:
前端代码中用JSON.parse(greeting.body).content解析消息,但start方法直接发送字符串"Let's play!",字符串无法被JSON解析,会在浏览器控制台抛出错误,导致消息无法展示。解决:start方法中同样发送GreetingWS对象,比如messageTemplate.convertAndSend("/topic/greetings", new GreetingWS("Let's play!"));方法返回值错误:
login方法要求返回GreetingWS类型,但start方法返回void,这会导致编译错误,else分支的start()调用根本无法正常执行,先修复这个编译问题。指定用户发送的前提配置:
要实现按用户身份发消息,需要:- 配置Spring Security或自定义认证逻辑,让每个WebSocket连接关联用户身份;
- 发送时使用
messageTemplate.convertAndSendToUser(username, "/queue/private", message),前端订阅目标为/user/queue/private(/user是框架默认的用户专属前缀); - 确保WebSocket配置中开启用户目标支持(默认已支持,无需额外配置)。
内容的提问来源于stack exchange,提问作者Alanight

