springboot+websocket+sockjs进行消息推送【基于STOMP协议】

本文介绍如何在SpringBoot项目中利用WebSocket实现服务器与客户端之间的全双工通讯,包括环境搭建、配置及实现一对多消息推送。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.浅谈WebSocket

WebSocket是在HTML5基础上单个TCP连接上进行全双工通讯的协议,只要浏览器和服务器进行一次握手,就可以建立一条快速通道,两者就可以实现数据互传了。说白了,就是打破了传统的http协议的无状态传输(只能浏览器请求,服务端响应),websocket全双工通讯,就是浏览器和服务器进行一次握手,浏览器可以随时给服务器发送信息,服务器也可以随时主动发送信息给浏览器了。对webSocket原理有兴趣的客官,可以自行百度。

2.环境搭建

因为是根据项目的需求来的,所以这里我只介绍在SpringBoot下使用WebSocket的其中一种实现【STOMP协议】。因此整个工程涉及websocket使用的大致框架为SpringBoot+Maven+websocket,其他框架的基础搭建,我这里就不说了,相信各位也都很熟悉,我就直接集成websocket了。

在pox.xml加上对springBoot对WebSocket的支持:

<!-- webSocket -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
这样SpringBoot就和WebSocket集成好了,我们就可以直接使用SpringBoot提供对WebSocket操作的API了

3.编码实现

①在Spring上下文中添加对WebSocket的配置

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
 
/**
 * 配置WebSocket
 */
@Configuration
//注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping,就像使用@RequestMapping一样
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{
    @Override
    //注册STOMP协议的节点(endpoint),并映射指定的url
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册一个STOMP的endpoint,并指定使用SockJS协议
        registry.addEndpoint("/endpointOyzc").setAllowedOrigins("*").withSockJS();
    }
    @Override
    //配置消息代理(Message Broker)
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //点对点应配置一个/user消息代理,广播式应配置一个/topic消息代理
        registry.enableSimpleBroker("/topic","/user");
        //点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/
        registry.setUserDestinationPrefix("/user");
    }
}
介绍以上几个相关的注解和方法:

1.@EnableWebSocketMessageBroker:开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping,就像使用@RequestMapping一样。

2.AbstractWebSocketMessageBrokerConfigurer:继承WebSocket消息代理的类,配置相关信息。

3.registry.addEndpoint("/endpointOyzc").setAllowedOrigins("*").withSockJS(); 添加一个访问端点“/endpointGym”,客户端打开双通道时需要的url,允许所有的域名跨域访问,指定使用SockJS协议。

4. registry.enableSimpleBroker("/topic","/user"); 配置一个/topic广播消息代理和“/user”一对一消息代理

5. registry.setUserDestinationPrefix("/user");点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/

 

②实现服务器主动向客户端推送消息

SpringBoot封装得太好,webSocket用起来太简单(好处:用起来方便,坏处:你不知道底层实现)

1.一对多的实现:

先上后台java的代码

package com.cheng.sbjm.boot;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import com.cheng.sbjm.domain.User;
 
@Controller
public class WebSocketController {
    
    @Autowired
    private SimpMessagingTemplate template;
    
    //广播推送消息
    @Scheduled(fixedRate = 10000)
    public void sendTopicMessage() {
    System.out.println("后台广播推送!");
    User user=new User();
    user.setUserName("oyzc");
    user.setAge(10);
        this.template.convertAndSend("/topic/getResponse",user);
    }
}
简单介绍一下

1.SimpMessagingTemplate:SpringBoot提供操作WebSocket的对象

2.@Scheduled(fixedRate = 10000):为了测试,定时10S执行这个方法,向客户端推送

3.template.convertAndSend("/topic/getResponse",new AricResponse("后台实时推送:,Oyzc!")); :直接向前端推送消息。

3.1参数一:客户端监听指定通道时,设定的访问服务器的URL

3.2参数二:发送的消息(可以是对象、字符串等等)

 

在上客户端的代码(PC现代浏览器)

html页面:

<!DOCTYPE html>
<html>
  <head>
    <title>websocket.html</title>    
    <meta name="keywords" content="keyword1,keyword2,keyword3">
    <meta name="description" content="this is my page">
    <meta name="content-type" content="text/html" charset="UTF-8">
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->    
  </head>  
  <body>
    <div>  
        <p id="response"></p>
    </div>
    
    <!-- 独立JS -->
    <script type="text/javascript" src="jquery.min.js" charset="utf-8"></script>
    <script type="text/javascript" src="webSocket.js" charset="utf-8"></script>
    <script type="text/javascript" src="sockjs.min.js" charset="utf-8"></script>
    <script type="text/javascript" src="stomp.js" charset="utf-8"></script>
  </body>
</html>

### Spring Boot 中实现 WebSocket 消息推送 #### 1. WebSocket 的基本概念 WebSocket 是一种基于 TCP 协议的全双工通信协议,能够在单个 TCP 连接上进行双向数据传输[^5]。相比传统的 HTTP 轮询方式,WebSocket 提供了更低延迟和更高效率的消息传递机制。 #### 2. 配置 Spring Boot 和 WebSocket 为了在 Spring Boot 应用程序中启用 WebSocket 支持,需要引入依赖项并配置相应的组件: ##### 添加 Maven 或 Gradle 依赖 ```xml <!-- Maven --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> // Gradle implementation 'org.springframework.boot:spring-boot-starter-websocket' ``` ##### 创建 WebSocket 配置类 通过扩展 `AbstractWebSocketMessageBrokerConfigurer` 类来设置消息代理: ```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.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @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("/ws").withSockJS(); // 注册 STOMP 终端点 } } ``` #### 3. 控制器处理逻辑 创建一个控制器用于接收客户端发送的消息,并将其转发至订阅者: ```java import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; @Controller public class MessageController { @MessageMapping("/sendMessage") // 接收来自 /app/sendMessage 的消息 @SendTo("/topic/messages") // 将消息广播到 /topic/messages 订阅者 public String handleMessage(String message) { return "Received: " + message; // 返回响应内容 } } ``` #### 4. 前端 Vue.js 实现 WebSocket 客户端 前端可以通过 SockJSStomp 来建立 WebSocket 连接并与后端交互: ##### HTML 页面结构 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebSocket Example</title> <!-- 引入 sockjs-client 和 stomp.js --> <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/stompjs/lib/stomp.min.js"></script> </head> <body> <div id="app"> <h1>WebSocket Chat</h1> <input type="text" v-model="message" placeholder="Enter your message"/> <button @click="send">Send</button> <ul> <li v-for="(msg, index) in messages" :key="index">{{ msg }}</li> </ul> </div> <script> const app = new Vue({ el: '#app', data() { return { message: '', messages: [], stompClient: null, }; }, mounted() { this.connect(); }, methods: { connect() { const socket = new SockJS('/ws'); // 对应后端注册的终端点 this.stompClient = Stomp.over(socket); this.stompClient.connect({}, frame => { console.log('Connected:', frame); this.stompClient.subscribe('/topic/messages', response => { // 订阅主题 this.messages.push(JSON.parse(response.body).content); // 显示收到的消息 }); }); }, send() { this.stompClient.send("/app/sendMessage", {}, JSON.stringify({ content: this.message })); // 发送消息 this.message = ''; } } }); </script> </body> </html> ``` #### 5. 解决常见问题 如果在 WebSocket 服务类中尝试注入其他 Bean(如 Service),可能会遇到空指针异常。这是由于 WebSocket 默认以多实例形式运行,而 Spring 管理的对象通常是单例模式。解决方法是在需要的地方显式声明作用域或使用静态变量存储上下文中的 Bean[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值