在 SpringBoot 和 React 中配置 WebSocket

本文将逐步介绍如何在 Spring Boot 中配置 WebSocket 并将其与 React 配合使用。

在 SpringBoot 和 React 中配置 WebSocket

依赖项

我们只需要两个依赖项,尽量减少所需的依赖项数量。

 <dependencies>
    <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <scope>provided</scope>
    </dependency>
 </dependencies>

配置

接下来,我们将创建 WebSocketConfig 配置类。它实现了 WebSocketMessageBrokerConfigurer,并注释了 Configuration EnableWebSocketMessageBroker

Configuration 表示该类是 Spring 配置类,用于为应用程序定义 Spring Bean 和配置。

@EnableWebSocketMessageBroker 在应用程序中启用基于 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("/")
          .setAllowedOrigins("http://localhost:3000")
          .withSockJS();
 }
}

现在,让我们来看看 WebSocketConfig 类中的方法:

配置消息代理

configureMessageBroker(MessageBrokerRegistry config): 该方法用于配置 WebSocket 的消息代理。

config.enableSimpleBroker("/topic")启用简单消息代理,允许客户端订阅和接收来自指定目标前缀(即/topic)的消息。服务器发送到以 /topic 开头的主题的消息将广播给连接的客户端。

config.setApplicationDestinationPrefixes("/app")设置应用程序目标前缀。客户端可以向以此前缀开头的目的地发送信息。例如,客户端可以向 /app/destination 发送信息。

注册 Stomp 端点

registerStompEndpoints(StompEndpointRegistry registry)注册一个客户可以连接的 Stomp(面向简单文本的消息传递协议)端点。

registry.addEndpoint("/")将根端点(i.e., “/”)注册为 WebSocket 端点。客户端可以连接到该端点来建立 WebSocket 连接,我们将在 React 应用程序中看到如何实现。

withSockJS()支持 SockJS,这是一个 JavaScript 库,为不直接支持 WebSocket 的浏览器提供类似 WebSocket 的接口。这样可以实现更广泛的客户端兼容性。

控制器

下面创建一个简单的控制器:

@Slf4j
@Controller
public class WebSocketController {

 private final Map<String, List<UserText>> chats = new HashMap<>();

 @MessageMapping("/chat/{chatId}")
 @SendTo("/topic/chat/{chatId}")
 public List<UserText> sendMessageWithWebsocket(@DestinationVariable String chatId,
   @Payload Message<UserText> message) {
  log.info("new message arrived in chat with id {}", chatId);
  List<UserText> messages = this.chats.getOrDefault(chatId, new ArrayList<UserText>());
  messages.add(message.getPayload());
  chats.put(chatId, messages);
  return messages;
 }
}

在这里,我们将消息存储在一个名为 messages 的数组中,然后将该数组存储在一个以聊天 ID 为标识符的映射中。通过注解 @DestinationVariable,我们可以获得聊天 ID。每个用户都将订阅不同的对话,并只能查看该聊天中的消息。

启动应用程序并在终端运行以下命令,检查是否能成功连接到 WebSocket 端点。

wscat -c ws://localhost:8080/websocket

构建简单的 React 应用程序

要连接 React,需要以下依赖关系:

npm install --save @stomp/stompjs

编辑App.tsx

import { Client } from '@stomp/stompjs';
import { useEffect, useState } from 'react';
import './App.css';
import logo from './logo.svg';

function App() {
  let client: Client | null = null;

  const [chatId, setChatId] = useState("")

  useEffect(() => {
    // Create a WebSocket connection

    client = new Client();

    // Configure the WebSocket endpoint URL
    const websocketUrl = 'ws://localhost:8080/websocket'; // Replace with your WebSocket endpoint URL

    // Connect to the WebSocket server
    client.configure({
      brokerURL: websocketUrl,
      debug: function (str) {
        console.log(str);
      },
      onConnect: () => {
        // Perform actions after successful connection
        const destination = `/topic/chat/${chatId}`; // Specify the destination for the server-side message handler
        client && client.subscribe(destination, (message) => {
          console.log('Received message:', JSON.parse(message.body));
          // Process the received message as needed
        });
      },
      // You can add more event handlers and configuration options as needed
    });

    // Connect to the WebSocket server
    client.activate();


    // Clean up the connection on component unmount
    return () => {
      client && client.deactivate();
    };
  }, [chatId]);


  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          <input type='text' aria-label='ChatId' onChange={(event) => {
            console.log(event)
            setChatId(event.target.value)
          }}></input>
          <button onClick={() => {
            const destination = `/app/chat/${chatId}`; // Specify the destination for the server-side message handler
            const message = 'Hello, server!'; // Specify the message to send
            if (client != null) {
              client.publish({
                destination,
                body: JSON.stringify({
                  data: message,
                  userId: 1 // Specify a user ID
                }),
              });
            }
          }}>Send</button>
        </p>
      </header>
    </div>
  );
}

export default App;

以上代码完整Github地址: https://github.com/lejdiprifti/medium

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论