Spring Boot项目中使用WebSocket消息代理功能

  1. 添加依赖 :在pom.xml文件中添加Spring Boot的WebSocket依赖。

    复制代码
    <dependencies>
        <!-- Spring Boot Starter Websocket -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
    </dependencies>
  2. WebSocket配置类 (WebSocketConfig.java):

    import org.springframework.context.annotation.Configuration;
    import org.springframework.messaging.simp.config.MessageBrokerRegistry;
    import org.springframework.web.socket.config.annotation.*;

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    复制代码
     @Override
     public void registerStompEndpoints(StompEndpointRegistry registry) {
         //这个代表了前端需要通过/ws路径来建立连接
         registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
     }
    
     @Override
     public void configureMessageBroker(MessageBrokerRegistry registry) {
         //这个你就把它当作创建了"/topic", "/queue"这两个频道,然后前端建立连接后
         //可以监听这两个频道,后端发送消息到这其中频道后,前端可以接收到
         registry.enableSimpleBroker("/topic", "/queue");
         //这个代表前端可以通过/user开头的地址,来给服务端发送消息,服务端可以用     
         //@MessageMapping注解来接收消息
         // @MessageMapping("/sendMessage") 例如这样写,前端就需要通过/user/sendMessage来给后        
         //端的这个方法发送消息
         registry.setUserDestinationPrefix("/user");
     }

    }

WebSocket控制器 (WebSocketController.java):

复制代码
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class WebSocketController {
    //接收客户端向/user/sendMessage这个地址发送的消息
    @MessageMapping("/sendMessage")
    //把接收来的这个消息发送到所有订阅/topic/messages地址的客户端
    @SendTo("/topic/messages")
    public String processMessageFromClient(String message) {
        return "Server response: " + message;
    }
}

让你更便于理解,我这么写:

当客户端通过 /sendMessage 发送消息时,processMessageFromClient 方法会被调用,并将消息传递给 sendToTopicMessages 方法。sendToTopicMessages 方法会返回一个格式化的响应消息,该消息会被发送到 /topic/messages 主题(订阅频道)。

复制代码
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class WebSocketController {

    @MessageMapping("/sendMessage")
    public String processMessageFromClient(String message) {
        // 调用 sendToTopicMessages 并使用其返回值
        return sendToTopicMessages(message);
    }

    @SendTo("/topic/messages")
    public String sendToTopicMessages(String message) {
        // 返回服务器响应的消息
        return "Server response: " + message;
    }
}

当然你也可以不适用@SendTo注解来向订阅地址发送消息。

SimpMessagingTemplate 是 Spring Framework 中的一个类,它提供了向 WebSocket 客户端发送消息的多种方法。

复制代码
以下是一些主要方法:

1. **convertAndSend**:这是最常用的方法,用于将消息转换并发送到指定目的地。它支持发送文本消息、二进制消息和对象消息等。例如,`convertAndSend("/topic/greetings", "Hello World!")` 会向所有订阅了 `/topic/greetings` 的客户端发送一条文本消息  。

2. **convertAndSendToUser**:此方法允许你向特定用户发送消息。它需要用户的标识符、目的地和消息内容。例如,`convertAndSendToUser("user1", "/queue/notifications", message)` 会向用户 `user1` 发送消息  。

3. **setUserDestinationPrefix**:设置用于针对特定用户的目标地址的前缀。默认值是 `"/user/"`。此方法通常与 `convertAndSendToUser` 结合使用,以确保消息发送到正确的用户端点 。

4. **getMessageChannel**:返回配置的消息通道,该通道用于发送消息 。

5. **setSendTimeout** 和 **getSendTimeout**:用于设置和获取发送操作的超时时间(以毫秒为单位)。

6. **send**:发送一个 `Message` 对象到指定的目的地。如果消息头中已经包含了目的地,则消息将直接发送到该目的地;如果没有,则会发送到配置的默认目的地 。

`SimpMessagingTemplate` 的使用需要在项目中添加 Spring Boot 的 WebSocket 依赖 `spring-boot-starter-websocket` 。通过注入 `SimpMessagingTemplate` 的实例,你可以在 Spring Boot 应用程序的任何地方发送消息,甚至不必首先接收一条消息作为前提 。

在实际开发中,`SimpMessagingTemplate` 可以用于实现如聊天应用、实时数据推送等需要 WebSocket 通信的功能。使用时,可以通过配置文件或注解来启用 WebSocket 支持,并利用 `SimpMessagingTemplate` 的方法来处理消息的发送 。

前端页面 (index.html):

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/stompjs/lib/stomp.min.js"></script>
</head>
<body>
    <h1>WebSocket Demo</h1>
    <input type="text" id="message" placeholder="Type a message">
    <button onclick="sendMessage()">Send</button>
    <h2>Messages</h2>
    <ul id="messages"></ul>

    <script type="text/javascript">
        const socket = new SockJS('/ws');
        const stompClient = Stomp.over(socket);
        let connected = false;

        function connect() {
            stompClient.connect({}, frame => {
                connected = true;
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/messages', message => displayMessage(message));
            });
        }

        function sendMessage() {
            const messageInput = document.getElementById('message');
            if (connected) {
                stompClient.send("/app/sendMessage", {}, messageInput.value);
                messageInput.value = '';
            } else {
                alert("Please connect first!");
            }
        }

        function displayMessage(message) {
            const messagesList = document.getElementById('messages');
            const messageItem = document.createElement('li');
            messageItem.textContent = message.body;
            messagesList.appendChild(messageItem);
        }

        socket.onclose = () => {
            connected = false;
            console.log("Disconnected");
        };

        window.onload = connect; // Connect when the page loads
    </script>
</body>
</html>

这样你打开html页面,可以多开几个浏览器。

然后在任意页面发送消息,其他浏览器都会接收并且显示出来,包括发送方的页面也会显示。因为大家都订阅了/topic/messages频道

相关推荐
风象南3 分钟前
SpringBoot 控制器的动态注册与卸载
java·spring boot·后端
我是一只代码狗29 分钟前
springboot中使用线程池
java·spring boot·后端
hello早上好42 分钟前
JDK 代理原理
java·spring boot·spring
PanZonghui1 小时前
Centos项目部署之运行SpringBoot打包后的jar文件
linux·spring boot
沉着的码农1 小时前
【设计模式】基于责任链模式的参数校验
java·spring boot·分布式
zyxzyx6661 小时前
Flyway 介绍以及与 Spring Boot 集成指南
spring boot·笔记
一头生产的驴3 小时前
java整合itext pdf实现自定义PDF文件格式导出
java·spring boot·pdf·itextpdf
程序员张36 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
麦兜*12 小时前
Spring Boot启动优化7板斧(延迟初始化、组件扫描精准打击、JVM参数调优):砍掉70%启动时间的魔鬼实践
java·jvm·spring boot·后端·spring·spring cloud·系统架构
KK溜了溜了12 小时前
JAVA-springboot 整合Redis
java·spring boot·redis