Spring Boot 与 WebSocket:实时双向通信的实现!

举报
bug菌 发表于 2025/07/16 15:31:33 2025/07/16
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8 🚀 前言随着互联网技术的飞速发展,实时通信技术已经逐渐成为现代Web...

🏆本文收录于「滚雪球学SpringBoot」专栏(全网一个名),手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

🚀 前言

随着互联网技术的飞速发展,实时通信技术已经逐渐成为现代Web应用的核心需求。无论是在即时消息系统、在线游戏、金融交易平台,还是物联网(IoT)应用中,WebSocket都提供了一种高效、持久的双向通信方式。特别是在需要低延迟的场景下,WebSocket的优势尤为突出。本文将深入解析如何利用Spring Boot实现WebSocket通信,进而结合STOMP协议,构建一个功能强大的实时聊天室应用。

🎯 WebSocket协议简介

WebSocket协议自HTML5引入以来,成为了现代Web应用的重要组成部分。它打破了传统HTTP协议只能在请求和响应的周期内进行单向通信的限制,实现了双向通信,并保持持久连接。

WebSocket协议的优势

  1. 低延迟:WebSocket连接是持久性的连接,避免了频繁的握手过程。消息从客户端到服务器,再到客户端的延迟极低,非常适合即时通讯和实时推送场景。
  2. 节省带宽:相比HTTP的请求-响应模式,WebSocket连接不需要每次传输都重新建立连接,节省了很多带宽和计算资源。
  3. 全双工通信:客户端和服务器都可以随时发送数据,不需要等待对方回应。这使得实时互动应用变得更加灵活和高效。

WebSocket的应用场景

  • 实时聊天:例如即时通讯、客服系统,WebSocket允许即时传递消息。
  • 实时数据推送:例如股市行情、体育比赛实时得分等,WebSocket使得数据可以实时推送到客户端。
  • 在线游戏:WebSocket能够实现游戏玩家之间的即时互动和实时数据同步。
  • 物联网(IoT):WebSocket能够帮助传感器和设备实时通信,提供更及时的数据反馈。

🛠️ Spring Boot 中实现 WebSocket

Spring Boot 是一个开箱即用的框架,集成了多种常用功能,帮助开发者快速实现应用的功能。Spring Boot 对 WebSocket 的支持非常全面,允许我们轻松地配置 WebSocket 服务。

1. 配置 WebSocket 端点

在 Spring Boot 中配置 WebSocket 服务非常简单,我们需要做以下几步:

  • 创建一个 WebSocket 配置类,并使用 @EnableWebSocket 注解启用 WebSocket 功能。
  • 在配置类中注册 WebSocket 端点,配置客户端连接路径。
package com.example.websocket.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 注册WebSocketHandler,"/chat"是客户端连接WebSocket时访问的路径
        registry.addHandler(new WebSocketHandlerImpl(), "/chat")
                .setAllowedOrigins("*");  // 允许跨域请求
    }
}

2. 创建 WebSocket 处理类

WebSocket 处理类负责接收客户端发送的消息并做出响应。我们通过继承 TextWebSocketHandler 类来实现消息的处理:

package com.example.websocket.handler;

import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class WebSocketHandlerImpl extends TextWebSocketHandler {

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        try {
            // 处理客户端发送的消息,并向客户端发送回应消息
            System.out.println("Received message: " + message.getPayload());
            session.sendMessage(new TextMessage("Echo: " + message.getPayload()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("WebSocket connection established");
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("WebSocket connection closed");
    }
}

3. 客户端的 WebSocket 连接

在前端页面,我们使用原生 JavaScript 创建 WebSocket 连接。客户端通过 new WebSocket() 方法与服务器建立连接:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket Chat</title>
</head>
<body>
    <h1>WebSocket Chat</h1>
    <div>
        <input type="text" id="messageInput" placeholder="Enter a message">
        <button onclick="sendMessage()">Send</button>
    </div>
    <div id="messages"></div>

    <script>
        const socket = new WebSocket("ws://localhost:8080/chat");

        // 接收服务器发送的消息
        socket.onmessage = function(event) {
            const message = event.data;
            const messagesDiv = document.getElementById("messages");
            const newMessage = document.createElement("p");
            newMessage.textContent = message;
            messagesDiv.appendChild(newMessage);
        };

        // 向服务器发送消息
        function sendMessage() {
            const messageInput = document.getElementById("messageInput");
            const message = messageInput.value;
            socket.send(message);
            messageInput.value = '';  // 清空输入框
        }
    </script>
</body>
</html>

在这个例子中,我们创建了一个简单的聊天室应用,前端通过 WebSocket 与后端建立了连接,客户端输入消息并通过 WebSocket 发送给服务器,服务器将其原样返回。

📨 WebSocket 与 STOMP 协议集成

虽然 WebSocket 本身支持双向通信,但它的消息处理方式较为基础,适合一些简单的场景。然而,STOMP 协议为 WebSocket 提供了更加高级的消息处理机制,能够实现消息的广播、订阅、队列处理等。

1. 引入 STOMP 依赖

首先,我们需要在 pom.xml 中引入 spring-boot-starter-websocketspring-messaging 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.messaging</groupId>
    <artifactId>spring-messaging</artifactId>
</dependency>

2. WebSocket 配置与 STOMP 协议启用

通过 @EnableWebSocketMessageBroker 注解启用 STOMP 协议,配置消息代理和 STOMP 端点。

package com.example.websocket.config;

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 registerStompEndpoints(StompEndpointRegistry registry) {
        // 注册STOMP端点,客户端将通过这个端点连接WebSocket
        registry.addEndpoint("/gs-guide-websocket").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 配置消息代理
        registry.setApplicationDestinationPrefixes("/app");
        registry.enableSimpleBroker("/topic");
    }
}

解释:

  • registerStompEndpoints 方法注册 STOMP 端点,客户端将通过该端点连接到 WebSocket 服务。
  • configureMessageBroker 方法启用消息代理,/app 是应用消息的前缀,/topic 是消息广播的主题。

3. WebSocket 控制器

使用 STOMP 协议时,我们可以通过 @MessageMapping 注解来接收客户端的消息,使用 @SendTo 注解广播消息:

package com.example.websocket.controller;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class ChatController {

    @MessageMapping("/chat.sendMessage")
    @SendTo("/topic/public")
    public String sendMessage(String message) throws Exception {
        return message;
    }
}

解释:

  • @MessageMapping("/chat.sendMessage") 表示当客户端发送消息到 /app/chat.sendMessage 时,方法将被触发。
  • @SendTo("/topic/public") 表示将结果发送到 /topic/public 主题,并广播给所有订阅该主题的客户端。

4. 前端页面集成 STOMP 协议

客户端通过 SockJSStomp.js 库与服务器建立 WebSocket 连接,并进行消息交换:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>STOMP WebSocket Chat</title>
    <script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/stompjs"></script>
</head>
<body>
    <h1>STOMP WebSocket Chat</h1>
    <div>
        <input type="text" id="messageInput" placeholder="Enter a message">
        <button onclick="sendMessage()">Send</button>
    </div>
    <div id="messages"></div>

    <script>
        const socket = new SockJS("/gs-guide-websocket");
        const stompClient = Stomp.over(socket);

        stompClient.connect({}, function (frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/public', function (messageOutput) {
                const message = messageOutput.body;
                const messagesDiv = document.getElementById("messages");
                const newMessage = document.createElement("p");
                newMessage.textContent = message;
                messagesDiv.appendChild(newMessage);
            });
        });

        function sendMessage() {
            const messageInput = document.getElementById("messageInput");
            const message = messageInput.value;
            stompClient.send("/app/chat.sendMessage", {}, message);
            messageInput.value = '';
        }
    </script>
</body>
</html>

解释:

  • SockJS 提供 WebSocket 降级支持,确保客户端在 WebSocket 不可用时也能连接。
  • stompClient.send("/app/chat.sendMessage", {}, message) 发送消息到服务器,服务器将消息广播到所有订阅的客户端。

🏁 小结

  • WebSocket 是一种持久连接协议,提供了低延迟的双向通信,适用于实时数据传输场景。
  • STOMP 协议 使 WebSocket 消息的处理更加高效,支持发布/订阅模型,适合于构建复杂的实时应用。
  • 使用 Spring Boot,我们能够轻松配置 WebSocket 和 STOMP,快速实现实时通信功能。

🏁 总结

通过本文的学习,我们了解了如何在 Spring Boot 中实现 WebSocket 双向通信,并结合 STOMP 协议构建一个简单的实时聊天应用。WebSocket 提供了高效的实时通信机制,而 STOMP 协议则为 WebSocket 提供了更加灵活的消息推送方式,能够满足复杂应用场景的需求。

实时通信是现代Web应用的重要组成部分,WebSocket 和 STOMP 协议为我们提供了低延迟、可靠的解决方案。通过结合 Spring Boot 的 WebSocket 支持,开发者可以非常方便地构建实时通信应用。掌握这些技术,可以为你在开发即时消息系统、在线游戏、物联网等应用中提供强有力的支持。

希望本文的深入解析能帮助你更好地理解 WebSocket 和 STOMP 协议的原理,并能够在实际项目中应用这些技术!

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」专栏(全网一个名),bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌(全网一个名),CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。