国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

SpringBoot+STOMP協(xié)議實(shí)現(xiàn)私聊、群聊

瀏覽:29日期:2023-03-05 14:11:28
目錄一、為什么需要STOMP?二、STOMP詳解三、SpringBoot集成STOMP代碼示例3.1、功能示例3.2、架構(gòu)圖3.3、服務(wù)端代碼3.4、h5代碼一、為什么需要STOMP?

WebSocket 協(xié)議是一種相當(dāng)?shù)图?jí)的協(xié)議。它定義了如何將字節(jié)流轉(zhuǎn)換為幀。幀可以包含文本或二進(jìn)制消息。由于消息本身不提供有關(guān)如何路由或處理它的任何其他信息,因此很難在不編寫其他代碼的情況下實(shí)現(xiàn)更復(fù)雜的應(yīng)用程序。幸運(yùn)的是,WebSocket 規(guī)范允許在更高的應(yīng)用程序級(jí)別上使用子協(xié)議。

另外,單單使用WebSocket完成群聊、私聊功能時(shí),需要自己管理session信息,通過(guò)STOMP協(xié)議時(shí),spring已經(jīng)封裝好,開(kāi)發(fā)者只需要關(guān)注自己的主題、訂閱關(guān)系即可。

二、STOMP詳解

SpringBoot+STOMP協(xié)議實(shí)現(xiàn)私聊、群聊

STOMP 中文為“面向消息的簡(jiǎn)單文本協(xié)議”,STOMP 提供了能夠協(xié)作的報(bào)文格式,以至于 STOMP 客戶端可以與任何 STOMP 消息代理(Brokers)進(jìn)行通信,從而為多語(yǔ)言,多平臺(tái)和 Brokers 集群提供簡(jiǎn)單且普遍的消息協(xié)作。STOMP 協(xié)議可以建立在 WebSocket 之上,也可以建立在其他應(yīng)用層協(xié)議之上。通過(guò) Websocket建立 STOMP 連接,也就是說(shuō)在 Websocket 連接的基礎(chǔ)上再建立 STOMP 連接。最終實(shí)現(xiàn)如上圖所示,這一點(diǎn)可以在代碼中有一個(gè)良好的體現(xiàn)。

業(yè)界已經(jīng)有很多優(yōu)秀的 STOMP 的服務(wù)器/客戶端的開(kāi)源實(shí)現(xiàn)

STOMP 服務(wù)器:ActiveMQ、RabbitMQ、StompServer、… STOMP 客戶端庫(kù):stomp.js(javascript)

Stomp 的特點(diǎn)是客戶端的實(shí)現(xiàn)很容易,服務(wù)端相當(dāng)于消息隊(duì)列的 broker 或者是 server,一般不需要我們?nèi)?shí)現(xiàn),所以重點(diǎn)關(guān)注一下客戶端如何使用

CONNECT 啟動(dòng)與服務(wù)器的流或 TCP 連接 SEND發(fā)送消息 SUBSCRIBE 訂閱主題 UNSUBSCRIBE 取消訂閱 BEGIN 啟動(dòng)事物 COMMIT提交事物 ABORT回滾事物 ACK確認(rèn)來(lái)自訂閱的消息的消費(fèi) NACK告訴服務(wù)器客戶端沒(méi)有消費(fèi)該消息 DISCONNECT斷開(kāi)連接

其實(shí)STOMP協(xié)議并不是為WS所設(shè)計(jì)的, 它其實(shí)是消息隊(duì)列的一種協(xié)議, 和AMQP,JMS是平級(jí)的。 只不過(guò)由于它的簡(jiǎn)單性恰巧可以用于定義WS的消息體格式。 目前很多服務(wù)端消息隊(duì)列都已經(jīng)支持了STOMP, 比如RabbitMQ, Apache ActiveMQ等。很多語(yǔ)言也都有STOMP協(xié)議的客戶端解析庫(kù),像JAVA的Gozirra,C的libstomp,Python的pyactivemq,JavaScript的stomp.js等等。

STOMP協(xié)議官方文檔

三、SpringBoot集成STOMP代碼示例3.1、功能示例

SpringBoot+STOMP協(xié)議實(shí)現(xiàn)私聊、群聊

SpringBoot+STOMP協(xié)議實(shí)現(xiàn)私聊、群聊

3.2、架構(gòu)圖

SpringBoot+STOMP協(xié)議實(shí)現(xiàn)私聊、群聊

3.3、服務(wù)端代碼

pom文件引入jar

<?xml version='1.0' encoding='UTF-8'?><project xmlns='http://maven.apache.org/POM/4.0.0' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd'> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>websocket-demo</artifactId> <version>1.0-SNAPSHOT</version> <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --> </parent> <properties><java.version>1.8</java.version> </properties> <dependencies><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId></dependency><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator-core</artifactId></dependency><dependency> <groupId>org.webjars</groupId> <artifactId>sockjs-client</artifactId> <version>1.0.2</version></dependency><dependency> <groupId>org.webjars</groupId> <artifactId>stomp-websocket</artifactId> <version>2.3.3</version></dependency><dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version></dependency><dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.1.0</version></dependency><dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version></dependency> </dependencies> <build><plugins> <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration> <source>1.8</source> <target>1.8</target></configuration> </plugin></plugins> </build></project>

WebSocketMessageBroker配置類

@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer{// 啟用一個(gè)簡(jiǎn)單的基于內(nèi)存的消息代理@Overridepublic void configureMessageBroker(MessageBrokerRegistry config) {//通過(guò)/topic 開(kāi)頭的主題可以進(jìn)行訂閱config.enableSimpleBroker('/topic');//send命令時(shí)需要帶上/app前綴config.setApplicationDestinationPrefixes('/app');//修改convertAndSendToUser方法前綴, 稍后解釋作用//config.setUserDestinationPrefix ('/myUserPrefix');}@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {//連接前綴registry.addEndpoint('/gs-guide-websocket').setAllowedOrigins('*') // 跨域處理.withSockJS(); //支持socketJs}}

@EnableWebSocketMessageBroker注解啟用 WebSocket 消息處理,由消息代理支持。

SockJS 有一些瀏覽器中缺少對(duì) WebSocket 的支持,而 SockJS 是一個(gè)瀏覽器的 JavaScript庫(kù),它提供了一個(gè)類似于網(wǎng)絡(luò)的對(duì)象,SockJS 提供了一個(gè)連貫的,跨瀏覽器的JavaScriptAPI,它在瀏覽器和 Web 服務(wù)器之間創(chuàng)建了一個(gè)低延遲、全雙工、跨域通信通道。SockJS 的一大好處在于提供了瀏覽器兼容性。即優(yōu)先使用原生WebSocket,如果瀏覽器不支持 WebSocket,會(huì)自動(dòng)降為輪詢的方式。如果你使用 Java 做服務(wù)端,同時(shí)又恰好使用 Spring Framework 作為框架,那么推薦使用SockJS。

控制器代碼

@Slf4j@RestControllerpublic class TestController{@Autowiredprivate SimpMessagingTemplate simpMessagingTemplate;@MessageMapping('/hello')@SendTo ('/topic/greetings')public Greeting greeting(HelloMessage message) throws Exception {Thread.sleep(1000); // simulated delayreturn new Greeting('Hello, ' + HtmlUtils.htmlEscape(message.getName()) + '!');}@MessageMapping('/topic/greetings')public Greeting greeting2(HelloMessage message) throws Exception {Thread.sleep(1000); // simulated delaylog.info ('Hello, ' + HtmlUtils.htmlEscape(message.getName()) + '!');return new Greeting('Hello, ' + HtmlUtils.htmlEscape(message.getName()) + '!');}@GetMapping ('/hello2')public void greeting3(HelloMessage message) throws Exception {Thread.sleep(1000); // simulated delaysimpMessagingTemplate.convertAndSend ('/topic/greetings',new Greeting('Hello, ' + HtmlUtils.htmlEscape(message.getName()) + '!'));}@MessageMapping('/sendToUser')public void sendToUser(HelloMessage message) throws Exception {Thread.sleep(1000); // simulated delaylog.info ('userId:{},msg:{}',message.getUserId (),message.getName ());//simpMessagingTemplate.convertAndSendToUser (message.getUserId (),'/sendToUser',//new Greeting('Hello, ' + HtmlUtils.htmlEscape(message.getName()) + '!'));//simpMessagingTemplate.convertAndSend ('/user/1/sendToUser',//new Greeting('Hello, ' + HtmlUtils.htmlEscape(message.getName()) + '!'));simpMessagingTemplate.convertAndSend ('/topic/user/'+message.getUserId ()+'/sendToUser',new Greeting('Hello, ' + HtmlUtils.htmlEscape(message.getName()) + '!'));}} @MessageMapping 功能與RequestMapping注解類似。send指令發(fā)送信息時(shí)添加此注解 @SendTo/@SendToUser 將信息輸出到該主題。客戶端訂閱同樣的主題后就會(huì)收到信息。 在只有指定@MessageMapping時(shí)@MessageMapping == “/topic” + @SendTo 如果想使用rest接口發(fā)送消息。可以通過(guò)SimpMessagingTemplate進(jìn)行發(fā)送。 點(diǎn)對(duì)點(diǎn)聊天時(shí),可以使用SimpMessagingTemplate.convertAndSendToUser方法發(fā)送。個(gè)人意味比注解@SendToUser更加容易理解,更加方便 convertAndSendToUser方法和convertAndSend類似,區(qū)別在于convertAndSendToUser方法會(huì)在主題默認(rèn)添加/user/為前綴。因此,示例代碼中convertAndSend方法直接傳入'/topic/user/'+message.getUserId ()+'/sendToUser' 也是點(diǎn)對(duì)點(diǎn)發(fā)送。topic其中是默認(rèn)前綴。 如果想修改convertAndSendToUser默認(rèn)前綴可在配置類進(jìn)行配置,可在WebSocketConfig類中查看。3.4、h5代碼

<!DOCTYPE html><html><head> <title>Hello WebSocket</title> <link href='http://www.cgvv.com.cn/webjars/bootstrap/css/bootstrap.min.css' rel='external nofollow' rel='stylesheet'> <link href='http://www.cgvv.com.cn/main.css' rel='external nofollow' rel='stylesheet'> <script type='text/javascript' src='https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js'></script> <script src='https://rkxy.com.cn/webjars/sockjs-client/sockjs.min.js'></script> <script src='https://rkxy.com.cn/webjars/stomp-websocket/stomp.min.js'></script> <script src='https://rkxy.com.cn/app.js'></script></head><body><noscript><h2 style='color: #ff0000'>Seems your browser doesn’t support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!</h2></noscript><div class='container'> <div class='row'><div class='col-md-6'> <form class='form-inline'><div class='form-group'> <label for='connect'>WebSocket connection:</label> <button type='submit'>Connect</button> <button type='submit' disabled='disabled'>Disconnect </button></div> </form></div><div class='col-md-6'> <form class='form-inline'><div class='form-group'> <label for='name'>What is your name?</label> <input type='text' placeholder='Your name here...'> <input type='text' placeholder='userId'></div><button type='submit'>Send</button><button type='submit'>Send2</button><button type='submit'>SendToUser</button> </form></div> </div> <div class='row'><div class='col-md-12'> <table class='table table-striped'><thead><tr> <th>Greetings</th></tr></thead><tbody id='greetings'></tbody> </table></div> </div></div></body></html>

app.js

var stompClient = null;var userId = null;function setConnected(connected) { $('#connect').prop('disabled', connected); $('#disconnect').prop('disabled', !connected); if (connected) {$('#conversation').show(); } else {$('#conversation').hide(); } $('#greetings').html('');}function connect() { var socket = new SockJS(’/gs-guide-websocket’); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) {setConnected(true);console.log(’Connected: ’ + frame);stompClient.subscribe(’/topic/greetings’, function (greeting) { showGreeting(JSON.parse(greeting.body).content);});//對(duì)應(yīng)controller greeting2方法 注意,這兒有兩個(gè)topic stompClient.subscribe(’/topic/topic/greetings’, function (greeting) {showGreeting(JSON.parse(greeting.body).content); }); stompClient.subscribe(’/topic/user/’+userId+’/sendToUser’, function (greeting) { showGreeting(JSON.parse(greeting.body).content); }); stompClient.subscribe(’/user/’+userId+’/sendToUser’, function (greeting) { showGreeting(JSON.parse(greeting.body).content); }); });}function disconnect() { if (stompClient !== null) {stompClient.disconnect(); } setConnected(false); console.log('Disconnected');}function sendName() { stompClient.send('/app/hello', {}, JSON.stringify({’name’: $('#name').val()}));// stompClient.send('/hello', {}, JSON.stringify({’name’: $('#name').val()}));}function sendName2() { stompClient.send('/app/topic/greetings', {}, JSON.stringify({’name’: $('#name').val()}));// stompClient.send('/topic/greetings', {}, JSON.stringify({’name’: $('#name').val()}));}function sendName3() { stompClient.send('/app/sendToUser', {}, JSON.stringify({’userId’:$('#userId').val(),’name’: $('#name').val()}));}function showGreeting(message) { $('#greetings').append('<tr><td>' + message + '</td></tr>');}function GetQueryString(name) {var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');var r = window.location.search.substr(1).match(reg); //獲取url中'?'符后的字符串并正則匹配var context = '';if (r != null)context = r[2];reg = null;r = null;return context == null || context == '' || context == 'undefined' ? '' : context;}$(function () { userId = GetQueryString('userId'); $('form').on(’submit’, function (e) {e.preventDefault(); }); $( '#connect' ).click(function() { connect(); }); $( '#disconnect' ).click(function() { disconnect(); }); $( '#send' ).click(function() { sendName(); }); $( '#send2' ).click(function() { sendName2(); }); $( '#send3' ).click(function() { sendName3(); });});

一些無(wú)關(guān)緊要的類

public class Greeting{ private String content; public Greeting() { } public Greeting(String content) { this.content = content; } public String getContent() { return content; }}

public class HelloMessage{ private String userId; private String name; // 省去get/set}Name3(); });});

spring參考文檔

websocket參考文檔

到此這篇關(guān)于SpringBoot+STOMP協(xié)議實(shí)現(xiàn)私聊、群聊的文章就介紹到這了,更多相關(guān)SpringBoot STOMP私聊、群聊內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 在线小毛片 | 日韩一级欧美一级 | 亚洲国产精品日韩在线 | 国产激情视频网站 | 男女视频在线观看 | 亚洲成 人a影院青久在线观看 | 北岛玲亚洲一区在线观看 | 黄色网址进入 | 亚洲欧美日韩久久一区 | 日本亚欧乱色视频在线观看 | 亚洲国产欧洲综合997久久 | 中国日本高清免费视频网 | 中文字幕成人在线 | 亚洲综合日韩精品欧美综合区 | 精品国产日韩亚洲一区在线 | 久久国产精品久久久 | 2019天天操天天干天天透 | 91亚洲精品国产第一区 | 日韩在线视精品在亚洲 | 久久视频在线观看免费 | 毛片免费全部免费观看 | 国内自拍视频在线播放 | 一色屋色费精品视频在线观看 | 免费看黄色的网址 | 亚洲免费一区 | 三级a黄| 国产黄色一级网站 | 在线观看人成网站深夜免费 | 国产成人精品免费视频大全可播放的 | 成a人片亚洲日本久久 | 精品视频在线视频 | 亚洲巨乳自拍在线视频 | 成人手机视频在线观看 | 亚洲一区二区三区四区五区 | 精品视频在线播放 | 在线看片一区 | 国产在线极品 | 久草热在线观看 | 欧美大片毛片aaa免费看 | 99国产在线播放 | 亚洲一级片免费看 |