在现代分布式系统和微服务架构中,消息驱动架构越来越受到关注。Spring Framework 提供了
Spring-Messaging
模块,使得开发者可以使用统一的消息传输抽象,同时支持多种消息协议,如 STOMP、AMQP 和 Kafka。本篇文章将深入解析Spring-Messaging
模块的核心功能,并通过 WebSocket + STOMP 示例,展示如何使用 Spring 实现高效的实时消息推送。
文章目录
- 1、Spring-Messaging 模块介绍
- 1.1、Spring-Messaging 模块概述
- 1.2、Spring-Messaging 模块依赖
- 1.3、Spring-Messaging 模块作用
- 2、基于 Spring-Messaging 的 **WebSocket + STOMP** 示例
- 2.1、引入 Maven 依赖
- 2. 2、WebSocket 配置
- 2.3. WebSocket 消息控制器
- 2.4、消息模型
- 2.5、Spring 配置文件(`spring-config.xml`)
- 2.6、前端 WebSocket 连接(`index.html`)
- 2.7、启动 Spring 容器
- X、后记
1、Spring-Messaging 模块介绍
1.1、Spring-Messaging 模块概述
Spring Messaging 模块,是 Spring Framework 的一部分,它为构建基于消息和事件驱动的应用程序提供了基础设施。
Spring Messaging 模块主要关注于消息的抽象处理,支持多种消息传递协议,并且特别强化了对反应式编程模型的支持,使得开发者能更方便地创建高性能、可扩展的分布式系统。
1.2、Spring-Messaging 模块依赖
Spring-Tx 模块的依赖有两个,分别是 Spring-Beans 模块和 Spring-Core 模块。
其中 Spring Beans 模块是对 Spring Bean 进行定义,实现 IOC 基础功能的模块。而 Spring-Core 是 Spring 中的基础模块,它提供了框架运行所必需的核心功能。
1.3、Spring-Messaging 模块作用
Spring-Messaging 的主要作用:
- 提供消息传输的抽象:通过
Message
、MessageChannel
、MessageHandler
等抽象,定义了一套标准的消息通信方式,使不同消息系统的使用更加统一。 - 支持 STOMP(Simple Text Oriented Messaging Protocol):可用于 WebSocket 的消息推送,例如聊天应用、实时数据更新等。
- 集成 Spring Integration:作为 Spring Integration 的一部分,帮助处理企业应用的集成需求,比如基于消息的微服务架构。
- 与 Spring AMQP(RabbitMQ)和 Spring Kafka 配合:
- 提供
@EnableRabbit
、@RabbitListener
等功能,简化 RabbitMQ 集成。 - 提供
@KafkaListener
处理 Kafka 消息。
- 提供
- 支持基于消息的事件驱动架构:结合
ApplicationEvent
和@EventListener
,可以在应用内部或分布式环境中进行事件驱动的异步通信。
2、基于 Spring-Messaging 的 WebSocket + STOMP 示例
以下是一个基于 Spring-Messaging 的 WebSocket + STOMP 示例
客户端 通过 WebSocket 发送消息 → 服务器 处理并广播 → 所有订阅者 接收消息,完成一个简单的 实时消息推送 系统。
2.1、引入 Maven 依赖
在 非 Spring Boot 的 Spring 项目中,spring-websocket
和 spring-messaging
需要手动引入:
<dependencies><!-- Spring 核心依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.39</version> </dependency><!-- Spring Web(提供 WebSocket 支持) --><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.39</version></dependency><!-- Spring WebSocket(支持 STOMP) --><dependency><groupId>org.springframework</groupId><artifactId>spring-websocket</artifactId><version>5.3.39</version></dependency><!-- Spring Messaging(提供消息传输的抽象) --><dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId><version>5.3.39</version></dependency><!-- Jackson(用于消息 JSON 解析) --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.3</version></dependency>
</dependencies>
2. 2、WebSocket 配置
在 非 Spring Boot 项目中,我们需要手动创建 ApplicationContext
并使用 @Configuration
进行配置:
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 // 启用 WebSocket 消息代理
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/ws") // WebSocket 端点.setAllowedOrigins("*") // 允许跨域.withSockJS(); // 兼容 SockJS}@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {registry.enableSimpleBroker("/topic"); // 配置消息代理(广播)registry.setApplicationDestinationPrefixes("/app"); // 以 "/app" 为前缀的请求交给控制器处理}
}
2.3. WebSocket 消息控制器
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") // 监听 "/app/chat"@SendTo("/topic/messages") // 将消息广播到 "/topic/messages"public MessageDTO sendMessage(MessageDTO message) {System.out.println("Received message from: " + message.getFrom());return new MessageDTO(message.getFrom(), "Replied: " + message.getContent());}
}
2.4、消息模型
public class MessageDTO {private String from;private String content;public MessageDTO() {}public MessageDTO(String from, String content) {this.from = from;this.content = content;}public String getFrom() { return from; }public void setFrom(String from) { this.from = from; }public String getContent() { return content; }public void setContent(String content) { this.content = content; }
}
2.5、Spring 配置文件(spring-config.xml
)
对于 非 Java 配置 的 Spring 项目,也可以使用 spring-config.xml
进行 Bean 配置:
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:websocket="http://www.springframework.org/schema/websocket"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/websockethttp://www.springframework.org/schema/websocket/spring-websocket.xsd"><!-- 开启组件扫描 --><context:component-scan base-package="com.example.websocket"/><!-- WebSocket 配置 --><websocket:message-broker><websocket:stomp-endpoint path="/ws"><websocket:sockjs/></websocket:stomp-endpoint><websocket:simple-broker prefix="/topic"/><websocket:application-destination-prefixes prefix="/app"/></websocket:message-broker></beans>
2.6、前端 WebSocket 连接(index.html
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.5.1/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script><script>var socket = new SockJS('/ws'); // 连接 WebSocket 端点var stompClient = Stomp.over(socket);stompClient.connect({}, function (frame) {console.log('Connected: ' + frame);// 订阅 "/topic/messages" 以接收服务器推送的消息stompClient.subscribe('/topic/messages', function (message) {var received = JSON.parse(message.body);console.log("Received message: ", received);document.getElementById("messages").innerHTML += "<p><b>" + received.from + ":</b> " + received.content + "</p>";});});function sendMessage() {var from = document.getElementById("name").value;var content = document.getElementById("message").value;stompClient.send("/app/chat", {}, JSON.stringify({from: from, content: content}));}
</script><input type="text" id="name" placeholder="Your Name">
<input type="text" id="message" placeholder="Type a message">
<button onclick="sendMessage()">Send</button>
<div id="messages"></div>
2.7、启动 Spring 容器
纯 Java 配置启动:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class WebSocketApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebSocketConfig.class);System.out.println("WebSocket server is running...");}
}
使用 XML 启动:
import org.springframework.context.support.ClassPathXmlApplicationContext;public class WebSocketApp {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");System.out.println("WebSocket server is running...");}
}
X、后记
通过本篇文章,我们深入了解了 Spring-Messaging
模块的核心概念,并基于 WebSocket 和 STOMP 实现了一个简单的实时消息推送系统。Spring-Messaging
不仅简化了消息传输的复杂性,还为分布式应用提供了灵活的事件驱动能力。在实际项目中,结合 RabbitMQ、Kafka 等消息中间件,可以进一步增强系统的可扩展性和稳定性。希望本篇文章能为你的 Spring 开发之旅提供有价值的参考!