在现代分布式系统和微服务架构中,消息驱动架构越来越受到关注。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 {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws") // WebSocket 端点
.setAllowedOrigins("*") // 允许跨域
.withSockJS(); // 兼容 SockJS
}
@Override
public 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/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/websocket
http://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 开发之旅提供有价值的参考!