基于 Spring Boot 的 WebSocket 使用

301 阅读2分钟

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它可以让服务器主动推送消息到客户端,避免了传统的 HTTP 请求-响应模式的弊端,非常适合实时通讯应用。Spring Boot 提供了非常方便的 WebSocket 支持,下面将介绍如何在 Spring Boot 中使用 WebSocket。

1. 环境搭建

首先,确保你的 Spring Boot 项目已经添加了 WebSocket 相关的依赖。在 pom.xml 中添加以下依赖:

xml
复制编辑
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

该依赖会自动引入 WebSocket 所需的库。

2. 创建 WebSocket 配置类

为了启用 WebSocket,需要在 Spring Boot 中配置 WebSocket。创建一个配置类来启用 WebSocket 支持:

java
复制编辑
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.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 设置消息代理(消息路由路径前缀)
        config.enableSimpleBroker("/topic", "/queue"); // 消息推送的目的地前缀
        config.setApplicationDestinationPrefixes("/app"); // 客户端发送消息时的路径前缀
    }

    @Override
    public void registerStompEndpoints(org.springframework.web.socket.config.annotation.StompEndpointRegistry registry) {
        // 设置 WebSocket 连接的端点
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }
}

在这个配置类中,我们做了以下几件事:

  • @EnableWebSocketMessageBroker:启用 WebSocket 消息代理功能。
  • 配置消息代理 /topic/queue,这些是服务端推送消息的目标路径。
  • 设置 WebSocket 连接的端点 /ws,并启用了 SockJS 支持,以兼容一些不支持 WebSocket 的浏览器。

3. 创建 WebSocket 控制器

创建一个 WebSocket 控制器,来处理消息的接收和推送。控制器中使用 @MessageMapping 来映射客户端消息,并通过 SimpMessagingTemplate 推送消息给客户端。

java
复制编辑
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class WebSocketController {

    @MessageMapping("/hello")  // 映射客户端发送到 /app/hello 的消息
    @SendTo("/topic/greetings")  // 向 /topic/greetings 主题发送消息
    public String greeting(String message) throws Exception {
        return "Hello, " + message + "!";
    }
}

在这个控制器中:

  • @MessageMapping("/hello"):监听客户端发送到 /app/hello 的消息。
  • @SendTo("/topic/greetings"):将返回的消息推送到 /topic/greetings 主题。

4. 客户端实现

客户端可以通过 HTML 和 JavaScript 来实现 WebSocket 的连接和消息收发。这里使用 STOMP 协议与 WebSocket 通信,可以通过 SockJS 实现兼容性。

html
复制编辑
<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Example</title>
    <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1.5.1/dist/sockjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/dist/stomp.min.js"></script>
</head>
<body>
    <div>
        <h1>WebSocket Example</h1>
        <input type="text" id="name" placeholder="Enter your name"/>
        <button onclick="sendMessage()">Send</button>
    </div>

    <div id="response"></div>

    <script type="text/javascript">
        var socket = new SockJS('/ws');  // 连接到 Spring Boot 后端的 WebSocket 端点
        var stompClient = Stomp.over(socket);

        stompClient.connect({}, function (frame) {
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/greetings', function (response) {
                document.getElementById("response").innerText = response.body;
            });
        });

        function sendMessage() {
            var name = document.getElementById("name").value;
            stompClient.send("/app/hello", {}, name);  // 向后端发送消息
        }
    </script>
</body>
</html>

在客户端实现中,做了以下几件事:

  • 使用 SockJS 连接到服务器端的 WebSocket 端点 /ws
  • 使用 STOMP 协议订阅 /topic/greetings 主题,接收到的消息将显示在页面中。
  • 输入框中输入名字后点击按钮,客户端会向服务器发送消息,并展示从服务器接收到的响应。