Spring Stomp 消息傳遞使用
1. 概述
STOMP(面向簡(jiǎn)單文本的消息傳遞協(xié)議)最初是為腳本語(yǔ)言(如 Ruby、Python 和 Perl)創(chuàng)建的,用于連接到企業(yè)消息代理。它旨在解決常用消息傳遞模式的最小子集。STOMP 可用于任何可靠的雙向流媒體網(wǎng)絡(luò)協(xié)議,例如 TCP 和 WebSocket。盡管 STOMP 是一種面向文本的協(xié)議,但消息有效負(fù)載可以是文本或二進(jìn)制的(來(lái)源spring官網(wǎng))
可以簡(jiǎn)單理解為是一種消息協(xié)議,與消息中間件(rabbitmq)類(lèi)似,存在消費(fèi)者和生產(chǎn)者以及broker(消息代理)。在一般的spring程序中,我們的程序即是broker也是生產(chǎn)者或者消費(fèi)者
Stomp協(xié)議是建立在websocket上面,算是對(duì)websocket的一種便捷使用
STOMP 消息發(fā)送與接收模型
下圖展示了 STOMP 協(xié)議中消息從發(fā)送到接收的完整流程,特別是 Spring 后端如何處理它們:
圖表關(guān)鍵點(diǎn)解釋?zhuān)?/h3>
1.連接建立
- 客戶(hù)端通過(guò) WebSocket(或 SockJS)連接到服務(wù)端的 STOMP 端點(diǎn)(如
/ws)。 - 服務(wù)端返回
CONNECTED幀,確認(rèn)連接已建立,此時(shí) STOMP 會(huì)話(huà)正式開(kāi)始。
2.訂閱目的地
- 客戶(hù)端向消息代理 發(fā)送
SUBSCRIBE幀,訂閱一個(gè)目的地(例如/topic/greetings)。 - 此后,任何發(fā)送到該目的地的消息都會(huì)被代理推送給這個(gè)客戶(hù)端。
3.發(fā)送消息與應(yīng)用邏輯處理
- 這是最核心的流程??蛻?hù)端發(fā)送
SEND幀到以/app為前綴的目的地(例如/app/hello)。 - 關(guān)鍵: 這個(gè)消息首先被 Spring 的
@MessageMapping注解所標(biāo)識(shí)的方法接收和處理。方法內(nèi)部可以包含任何業(yè)務(wù)邏輯。 - 處理完畢后,該方法可以通過(guò)返回一個(gè)值或使用
SimpMessagingTemplate,將一個(gè)新的消息發(fā)送到消息代理 上的某個(gè)目的地(通常是/topic或/queue)。
4.消息廣播/推送
- 消息代理 負(fù)責(zé)將接收到的消息(來(lái)自服務(wù)端)廣播給所有訂閱了該目的地的客戶(hù)端。
- 客戶(hù)端通過(guò)接收
MESSAGE幀來(lái)獲取消息內(nèi)容。
5.直接請(qǐng)求-響應(yīng)
- 這是一個(gè)特殊模式,使用
@SubscribeMapping。 - 當(dāng)客戶(hù)端訂閱以
/app為前綴的目的地時(shí),請(qǐng)求會(huì)直接到達(dá)控制器方法,該方法可以立即返回一個(gè)消息作為“響應(yīng)”,而無(wú)需經(jīng)過(guò)外部的消息代理。這適用于只需要獲取一次數(shù)據(jù)的場(chǎng)景。
Stomp前端使用
0.依賴(lài)
前端的類(lèi)庫(kù)選擇更多一些
可以使用@stomp/stompjs或者webstomp-client,前者使用簡(jiǎn)單,后者分裝得更好
stomp.js示例代碼:
npm i @stomp/stompjs
const stompClient = new StompJs.Client({
brokerURL: 'ws://localhost:8080/gs-guide-websocket'
});
stompClient.activate();
通過(guò)sockjs
import { Client } from '@stomp/stompjs';
import SockJS from 'sockjs-client';
const client = new Client({
webSocketFactory: () => new SockJS('http://localhost:15674/stomp'),
});
client.activate();
webstomp-client示例代碼:
npm install webstomp-client
var socket = new SockJS("/spring-websocket-portfolio/portfolio");
var stompClient = webstomp.over(socket);
stompClient.connect({}, function(frame) {
}
或者,如果您通過(guò) WebSocket(沒(méi)有 SockJS)進(jìn)行連接,則可以使用以下代碼:
var socket = new WebSocket("/spring-websocket-portfolio/portfolio");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
}
1.連接
stompClient.activate();
//或者webstomp-client
//connect(headers, connectCallback, errorCallback)
stompClient.connect({}, function (frame) {
resolve(frame);
}, function (error) {
reject("STOMP protocol error " + error);
});
2.訂閱
//它需要兩個(gè)必需參數(shù):destination(字符串)和 callback(接收消息的函數(shù)),以及用于其他標(biāo)頭的可選標(biāo)頭對(duì)象。
stompClient.subscribe('/topic/greetings', (greeting) => {
showGreeting(JSON.parse(greeting.body).content);
});
//或者webstomp-client
//subscribe(destination, callback, headers={})
stompClient.subscribe('/topic/greetings', function (message) {
show(JSON.parse(message.body));
});
3.發(fā)送
client.publish({destination: '/topic/general', body: 'Hello world'});
// There is an option to skip the Content-length header
client.publish({
destination: '/topic/general',
body: 'Hello world',
skipContentLengthHeader: true,
});
// Additional headers
client.publish({
destination: '/topic/general',
body: 'Hello world',
headers: {priority: '9'},
});
//或者webstomp-client
//send(destination, body='', headers={})
stompClient.send("/app/trade", JSON.stringify(tradeOrder), {})
4.關(guān)閉
stompClient.deactivate(); //或者webstomp-client stompClient.disconnect();
Stomp后端使用
依賴(lài)
stomp部分已經(jīng)包含在spring-websocket中,我們直接導(dǎo)入就可以了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
配置類(lèi)
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
//使用內(nèi)置消息代理進(jìn)行訂閱和廣播,以及將目標(biāo)標(biāo)頭以 /topic '或 '/queue 開(kāi)頭的消息路由到代理
config.enableSimpleBroker("/topic");
// 目標(biāo)標(biāo)頭以 /app 開(kāi)頭的 STOMP 消息將路由到 @MessageMapping @Controller 類(lèi)中的方法
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//websocket端點(diǎn)
registry.addEndpoint("/gs-guide-websocket");
}
}
注解發(fā)送和接收消息
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.util.HtmlUtils;
@Controller
public class GreetingController {
// 客戶(hù)端發(fā)送消息 /app/hello 會(huì)執(zhí)行這個(gè)方法
@MessageMapping("/hello")
// 將消息發(fā)送到這個(gè)地址的訂閱者
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
Thread.sleep(1000); // simulated delay
return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!");
}
}
編碼方式發(fā)送消息
@Controller
public class GreetingController {
private SimpMessagingTemplate template;
@Autowired
public GreetingController(SimpMessagingTemplate template) {
this.template = template;
}
@RequestMapping(path="/greetings", method=POST)
public void greet(String greeting) {
String text = "[" + getTimestamp() + "]:" + greeting;
this.template.convertAndSend("/topic/greetings", text);
}
}
到此這篇關(guān)于Spring Stomp 消息傳遞使用的文章就介紹到這了,更多相關(guān)Spring Stomp 消息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot項(xiàng)目部署到Tomcat的最新步驟
通過(guò)使用Spring Boot應(yīng)用程序,我們可以創(chuàng)建一個(gè)war文件來(lái)部署到Web服務(wù)器中,這篇文章主要給大家介紹了關(guān)于SpringBoot項(xiàng)目部署到Tomcat的最新步驟,需要的朋友可以參考下2024-01-01
java實(shí)現(xiàn)文本文件刪除空行的示例分享
這篇文章主要介紹了java實(shí)現(xiàn)文本文件刪除空行的示例,需要的朋友可以參考下2014-04-04
Java 遍歷取出Map集合key-value數(shù)據(jù)的4種方法
這篇文章主要介紹了Java 遍歷取出Map集合key-value數(shù)據(jù)的4種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Debian 7 和 Debian 8 用戶(hù)安裝 Java 8的方法
Oracle Java 8 穩(wěn)定版本近期已發(fā)布,有很多新的特征變化。其中,有功能的程序支持通過(guò)“Lambda項(xiàng)目 ”,收到了一些安全更新和界面改進(jìn)上的bug修復(fù),使得開(kāi)發(fā)人員的工作更容易。2014-03-03
Kotlin中使用Java數(shù)據(jù)類(lèi)時(shí)引發(fā)的Bug解決方式
這篇文章主要介紹了Kotlin中使用Java數(shù)據(jù)類(lèi)時(shí)引發(fā)的一個(gè)Bug,本文給大家分享問(wèn)題解決方式,感興趣的朋友跟隨小編一起看看吧2023-09-09
Java令牌Token登錄與退出的實(shí)現(xiàn)
這篇文章主要介紹了Java令牌Token登錄與退出的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
測(cè)試環(huán)境頻繁Full GC問(wèn)題的解決思路分析
全文介紹了作者通過(guò)與調(diào)用方交互,發(fā)現(xiàn)welink-front服務(wù)不可用的問(wèn)題,通過(guò)jmap-heap和jstat-gccause命令,作者找到了問(wèn)題的原因是元數(shù)據(jù)區(qū)內(nèi)存使用率過(guò)高,觸發(fā)了FullGC,作者通過(guò)分析GC日志和堆內(nèi)存使用情況,確定了問(wèn)題的根本原因2025-01-01
Java實(shí)現(xiàn)簡(jiǎn)單的斗地主游戲
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單的斗地主游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04

