首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Spring集成Websocket的两个问题

Spring集成Websocket的两个问题

作者头像
码农戏码
发布2026-06-25 19:58:06
发布2026-06-25 19:58:06
20
举报

最近在开发使用Websocket主动推送的功能,碰到一些问题,记录一下

前后端连接不通

基本spring-boot体系,集成Websocket是比较方便的

1、引入依赖包

代码语言:javascript
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2、加上配置类

代码语言:javascript
复制

@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 注册STOMP端点,客户端将使用它连接到我们的WebSocket服务器
        registry.addEndpoint("/ws")
                //.addInterceptors(new OriginHandshakeInterceptor(List.of("*")))
                .setAllowedOriginPatterns("*") // 允许所有来源(生产环境中应更严格)
                .withSockJS() // 启用SockJS回退选项
                .setClientLibraryUrl("https://cdn.bootcdn.net/ajax/libs/sockjs-client/1.6.1/sockjs.min.js");
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry)
    {

        //表明在topic、queue、users这三个域上可以向客户端发消息。
        registry.enableSimpleBroker("/topic","/queue","/users");
        //客户端向服务端发起请求时,需要以/app为前缀。
        registry.setApplicationDestinationPrefixes("/app");
        //给指定用户发送一对一的消息前缀是/user/。
        registry.setUserDestinationPrefix("/user/");
    }
}

但在与前端联调时,怎么也连接不上。

前端使用nodejs写了一个后端server,发现没问题。

后端使用AI也生成了一个前端demo,也没有问题。

后来发现,原因在于前后端使用的底层框架不一样。前端使用了Socket.IO,后端使用了SocketJS

在现代Web开发中,实时通信已经成为构建动态应用不可或缺的一部分

为了在浏览器中实现这一目标,WebSocket协议被广泛采用。然而,并非所有浏览器都原生支持WebSocket,这促使开发者寻找其他解决方案以确保更广泛的兼容性。

SockJS和Socket.IO是两种流行的解决方案,它们分别以不同的方式解决了这一问题。

SockJS和Socket.IO都是强大的实时通信库,它们提供了不同的方法来解决浏览器兼容性问题。

SockJS通过模拟WebSocket的行为,并提供了对多种浏览器传输方式的支持,

而Socket.IO则通过多种回退技术提供了更为全面的解决方案。在选择适合的库时,开发者应该根据项目需求、目标用户群体以及团队的技术栈来做出决定。无论如何,SockJS和Socket.IO都是在现代Web应用中实现实时通信的强大工具,它们极大地简化了开发者的工作,并使得构建实时应用成为可能。

总结与对比

特性

Spring Boot WebSocket

Socket.IO

核心协议

标准 WebSocket (RFC 6455)

自有协议(基于 WebSocket 增强)

兼容性方案

第一方集成 SockJS

内置自己的降级方案

高级功能

通过 STOMP 子协议 提供(订阅、发布、代理)。需要额外配置(如内存代理或RabbitMQ/ActiveMQ)。

内置(房间、自动重连、ACK等)

API 风格

基于注解的编程模型 (@MessageMapping),与 Spring MVC 风格一致。

事件驱动 (on, emit)

客户端需求

可以使用标准 WebSocket 客户端,但推荐使用 sockjs-client + stomp.js 以获得最佳体验和兼容性。

必须使用 Socket.IO 客户端库

解决方案

前后端使用相同的框架协议

@SendToUser与convertAndSendToUser()区别

一直没有搞明白这两者之间的区别是什么?

后端发送消息

代码语言:javascript
复制
SimpMessagingTemplate.convertAndSendToUser(username, "/queue/notifications",message);

前端订阅

代码语言:javascript
复制
//收不到消息
client.subscribe("/user/queue/notifications", handleNotifications);

//可以收到消息
client.subscribe("/user/jack/queue/notifications", handleNotifications);

这两种都是点对点,是什么区别。查了好些资料,也没有看明白。

再跑了跑demo,终于明白了其他人说的意思

1、两种的确都是点对点

2、两者的区别

代码语言:javascript
复制
/**
 * 当前端发送stompClient.send("/app/hello",message) 时,后端会把消息返回
 *
 * 返回到当前建立连接的端点destination=/user/topic/greetings
 */
@MessageMapping("/hello")
@SendToUser("/topic/greetings")
public Greeting greetingSendToUser(HelloMessage message) throws Exception {
    Thread.sleep(1000); // simulated delay
    Greeting sendToUser = new Greeting("Hello user: " + HtmlUtils.htmlEscape(message.getName()) + "!");
    /**
     * user jack在多个终端(打开了多个浏览器窗口),只要订阅了都能收到消息
     */
    messagingTemplate.convertAndSendToUser("jack", "/topic/greetings", sendToUser);
    return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
}

2.1 @SendToUser 只会发送到当前建立连接的destination上,不需要带具体的user信息,spring内部会帮忙处理

将原来的destination拼接为/user/userID/topic/greetings,userID是客户端的SessionID。拼接结果destination=“/user/au3ev44r/topic/greetings“

前端框架应该也有类似逻辑

2.2 convertAndSendToUser 不仅发送给建立连接的终端,还会发送给订阅了这个user信息所有的终端

Reference

https://juejin.cn/post/6844903661231947784

https://www.cnblogs.com/kakarotto-chen/p/17415808.html

https://potoyang.gitbook.io/spring-in-action-v4/untitled-11/untitled-2/untitled-1

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农戏码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前后端连接不通
    • 总结与对比
    • 解决方案
  • @SendToUser与convertAndSendToUser()区别
  • Reference
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档