2017-12-22

Java SpringBoot下的WebSocket

前面我們已經(jīng)講了如何搭建一個(gè)SpringBoot的Web框架,那么搭完了框架總要搞點(diǎn)事情吧具温,今天咱們就來做一個(gè)基于SpringBoot的簡易聊天室掠拳。

聊天

WebSocket簡介

工欲善其事必先利其器癞揉,我們先來講一下什么是WebScoket。WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議溺欧。它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信——允許服務(wù)器主動(dòng)發(fā)送信息給客戶端喊熟。,也就是說我們可以利用瀏覽器給服務(wù)器發(fā)送消息姐刁,服務(wù)器也可以給瀏覽器發(fā)送消息芥牌,目前的主流瀏覽器對WebSocket的支持都還不錯(cuò),但是在實(shí)際開發(fā)中使用WebSocket工作量會很大聂使,并且還有對瀏覽器的兼容問題壁拉,所以這個(gè)時(shí)候我們更多的是使用WebSocket的一個(gè)子協(xié)議stomp拐叉,利用它來快速實(shí)現(xiàn)我們的功能。

環(huán)境

我們做的建議公共聊天室需要在SpringBoot的POM文件中添加兩個(gè)依賴扇商,不知道怎么搭建SpringBoot的朋友可以看下我前面發(fā)的SpringBoot搭建的方法。

需要的maven依賴:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>

開始擼代碼

搭建完了基本的開發(fā)環(huán)境之后我們來寫代碼宿礁,首先我們先寫一個(gè)關(guān)于WebSocket的節(jié)點(diǎn)以及模式的配置類案铺,代碼里有詳細(xì)的注解。

package com.guanglan.config; 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; /** * Created by GuangLan on 2017/12/21. */ @Configuration //配置注解 @EnableWebSocketMessageBroker //@EnableWebSocketMessageBroker注解表示開啟使用STOMP協(xié)議來傳輸基于代理的消息梆靖,Broker就是代理的意思控汉。 public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { /** * configureMessageBroker用來配置消息代理模式,我們做的是公共聊天室所以用topic即可 * @param config */ @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); } /** * registerStompEndpoints方法表示注冊STOMP協(xié)議的節(jié)點(diǎn)返吻,并指定映射的URL的位置 * @param stompEndpointRegistry */ @Override public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) { //stompEndpointRegistry.addEndpoint("/MyWebsocket").withSockJS(); // 的意思就是注冊STOMP協(xié)議節(jié)點(diǎn)姑子,并且使用SockJS協(xié)議。 stompEndpointRegistry.addEndpoint("MyWebsocket").withSockJS(); } }

接下來我們要建立兩個(gè)實(shí)體類测僵,一個(gè)是接收客戶端發(fā)來的消息類街佑,一個(gè)是返回消息的類。

返回消息類:

package com.guanglan.entry; /** * 返回消息類 * Created by GuangLan on 2017/12/21. */ public class ResponseMessage { private String name; //消息發(fā)送者 private String message; //消息內(nèi)容 private String dateTime; //發(fā)送時(shí)間 public ResponseMessage(String name, String message,String dateTime){ this.name = name; this.message = message; this.dateTime = dateTime; } public String getResponseMessage(){ return "發(fā)送時(shí)間 : "+dateTime+"\n"+name+" : "+message+" "; } }

接收消息類:

package com.guanglan.entry; /** * 接收消息類 * Created by GuangLan on 2017/12/21. */ public class RequestMessage { private String name; //消息發(fā)送者 private String message; //消息內(nèi)容 public String getName() { return name; } public void setName(String name) { this.name = name; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }

接下來捍靠,我們建立接收消息和發(fā)送消息的控制類:

package com.guanglan.controller; import com.guanglan.entry.RequestMessage; import com.guanglan.entry.ResponseMessage; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; /** * Created by GuangLan on 2017/12/21. */ @Controller public class WebSocketController { @MessageMapping("/guanglan") //客戶端請求的地址 @SendTo("/topic/getResponse") //返回給客戶端消息的地址 public ResponseMessage responseMessage(RequestMessage message) { //獲取當(dāng)前時(shí)間 LocalDateTime localDateTime = LocalDateTime.now(); DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); //將從服務(wù)端接受的信息返回到頁面上 return new ResponseMessage(message.getName(),message.getMessage(),localDateTime.format(format)); } }

這樣主體流程就差不多了沐旨,我們在templates中建立一個(gè)名字為websocket的html5文件,并寫入以下內(nèi)容:

<html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>公共聊天室WebSocket</title> <link rel="stylesheet"/> <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"></script> <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js"></script> <script src="https://cdn.bootcss.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> </head> <body onload="disconnect()"> <noscript><h2 style="color: #e80b0a;">Sorry榨婆,瀏覽器不支持WebSocket</h2></noscript> <div> <div> <button id="connect" onclick="connect();" class="btn btn-success" style="width: 200px;height:60px;">連接</button> <button id="disconnect" disabled="disabled" onclick="disconnect();" class="btn btn-danger" style="width: 200px;height:60px;">斷開</button> </div> <div id="conversationDiv"> <div class="form-group"> <label for="name">姓名</label> <input type="text" id="name" class="form-control" placeholder="輸入你的名字" style="width: 500px;"/> </div> <div class="form-group"> <textarea id="message" class="form-control" rows="3" style="width: 500px;"> </textarea> </div> <button type="button" class="btn btn-info" id="sendName" onclick="sendName();">發(fā)送</button> <br/> <div class="form-group"> <p id="response"></p> </div> </div> </div> <script type="text/javascript"> var stompClient = null; function setConnected(connected) { document.getElementById("connect").disabled = connected; document.getElementById("disconnect").disabled = !connected; document.getElementById("conversationDiv").style.visibility = connected ? 'visible' : 'hidden'; $("#response").html(); } function connect() { var socket = new SockJS('/MyWebsocket'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { setConnected(true); stompClient.subscribe('/topic/getResponse', function (response) { showResponse(JSON.parse(response.body).responseMessage); }) }); } function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); } function sendName() { var name = $('#name').val(); var message = $('#message').val(); stompClient.send("/guanglan", {}, JSON.stringify({'name': name,'message':message})); } function showResponse(message) { $("#response").append("<br/>"+message); } </script> </body> </html>

馬上就要大功告成了磁携,不要?dú)怵H哦,我們在建立一個(gè)映射HTML5文件的類就OK了:

package com.guanglan.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * Created by GuangLan on 2017/12/21. */ @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { //訪問路徑以及頁面文件的名字 registry.addViewController("/websocket").setViewName("/websocket"); } }

這樣一個(gè)簡易的WebSocket聊天室就完成了良风。

主頁面

如果您按照上述地址訪問后出現(xiàn)上面的頁面那么恭喜您搭建成功了谊迄!

下面看看效果吧

效果圖

點(diǎn)擊鏈接后會出現(xiàn)聊天室的頁面,我在瀏覽器上建立了三個(gè)連接烟央,分別發(fā)送了消息统诺,效果如上。

好了吊档,今天的基于SpringBoot的簡易公共聊天室就講到這里篙议,如果您喜歡小編的作品請關(guān)注哦!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怠硼,一起剝皮案震驚了整個(gè)濱河市鬼贱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌香璃,老刑警劉巖这难,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異葡秒,居然都是意外死亡姻乓,警方通過查閱死者的電腦和手機(jī)嵌溢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹋岩,“玉大人赖草,你說我怎么就攤上這事〖舾觯” “怎么了秧骑?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長扣囊。 經(jīng)常有香客問我乎折,道長,這世上最難降的妖魔是什么侵歇? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任骂澄,我火速辦了婚禮,結(jié)果婚禮上惕虑,老公的妹妹穿的比我還像新娘坟冲。我一直安慰自己,他們只是感情好枷遂,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布樱衷。 她就那樣靜靜地躺著,像睡著了一般酒唉。 火紅的嫁衣襯著肌膚如雪矩桂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天痪伦,我揣著相機(jī)與錄音侄榴,去河邊找鬼。 笑死网沾,一個(gè)胖子當(dāng)著我的面吹牛癞蚕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辉哥,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼桦山,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了醋旦?” 一聲冷哼從身側(cè)響起恒水,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饲齐,沒想到半個(gè)月后钉凌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捂人,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年御雕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矢沿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡酸纲,死狀恐怖捣鲸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情闽坡,我是刑警寧澤摄狱,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站无午,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏祝谚。R本人自食惡果不足惜宪迟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望交惯。 院中可真熱鬧次泽,春花似錦、人聲如沸席爽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽只锻。三九已至玖像,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間齐饮,已是汗流浹背捐寥。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留祖驱,地道東北人握恳。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像捺僻,于是被迫代替她去往敵國和親乡洼。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理匕坯,服務(wù)發(fā)現(xiàn)束昵,斷路器,智...
    卡卡羅2017閱讀 134,600評論 18 139
  • 本文參考了:http://blog.didispace.com/springcloud7/http://blog....
    WeiminSun閱讀 7,185評論 0 23
  • spring官方文檔:http://docs.spring.io/spring/docs/current/spri...
    牛馬風(fēng)情閱讀 1,648評論 0 3
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評論 6 342
  • 有時(shí)候醒颖,你是否會覺得迷茫妻怎? 覺得世界不是你想要的! 覺得自己明明很努力泞歉,卻還是摸不到逼侦! 覺得自己很專心匿辩,卻還是敗給...
    崎漩閱讀 170評論 0 0