SpringBoot2.0整合WebSocket代碼實(shí)例
這篇文章主要介紹了SpringBoot2.0整合WebSocket代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
之前公司的某個(gè)系統(tǒng)為了實(shí)現(xiàn)推送技術(shù),所用的技術(shù)都是Ajax輪詢,這種方式瀏覽器需要不斷的向服務(wù)器發(fā)出請(qǐng)求,顯然這樣會(huì)浪費(fèi)很多的帶寬等資源,所以研究了下WebSocket,本文將詳細(xì)介紹下。
一、什么是WebSocket?
WebSocket是HTML5開(kāi)始提供的一種在單個(gè)TCP連接上進(jìn)行全雙工通訊的協(xié)議,能更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實(shí)時(shí)地進(jìn)行通訊。
WebSocket 使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允許服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù),在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。
二、SpringBoot整合WebSocket
新建一個(gè)spring boot項(xiàng)目spring-boot-websocket,按照下面步驟操作。
pom.xml引入jar包
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
新建WebSocket的配置類
這個(gè)配置類檢測(cè)帶注解@ServerEndpoint的bean并注冊(cè)它們,配置類代碼如下:
@Configuration public class WebSocketConfig { /** * 給spring容器注入這個(gè)ServerEndpointExporter對(duì)象 * 相當(dāng)于xml: * <beans> * <bean id="serverEndpointExporter" class="org.springframework.web.socket.server.standard.ServerEndpointExporter"/> * </beans> * <p> * 檢測(cè)所有帶有@serverEndpoint注解的bean并注冊(cè)他們。 * * @return */ @Bean public ServerEndpointExporter serverEndpointExporter() { System.out.println("我被注入了"); return new ServerEndpointExporter(); } }
新建WebSocket的處理類
這個(gè)處理類需要使用@ServerEndpoint,這個(gè)類里監(jiān)聽(tīng)連接的建立關(guān)閉、消息的接收等,具體代碼如下:
@ServerEndpoint(value = "/ws/asset") @Component public class WebSocketServer { @PostConstruct public void init() { System.out.println("websocket 加載"); } private static Logger log = LoggerFactory.getLogger(WebSocketServer.class); private static final AtomicInteger OnlineCount = new AtomicInteger(0); // concurrent包的線程安全Set,用來(lái)存放每個(gè)客戶端對(duì)應(yīng)的Session對(duì)象。 private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>(); /** * 連接建立成功調(diào)用的方法 */ @OnOpen public void onOpen(Session session) { SessionSet.add(session); int cnt = OnlineCount.incrementAndGet(); // 在線數(shù)加1 log.info("有連接加入,當(dāng)前連接數(shù)為:{}", cnt); SendMessage(session, "連接成功"); } /** * 連接關(guān)閉調(diào)用的方法 */ @OnClose public void onClose(Session session) { SessionSet.remove(session); int cnt = OnlineCount.decrementAndGet(); log.info("有連接關(guān)閉,當(dāng)前連接數(shù)為:{}", cnt); } /** * 收到客戶端消息后調(diào)用的方法 * * @param message * 客戶端發(fā)送過(guò)來(lái)的消息 */ @OnMessage public void onMessage(String message, Session session) { log.info("來(lái)自客戶端的消息:{}",message); SendMessage(session, "收到消息,消息內(nèi)容:"+message); } /** * 出現(xiàn)錯(cuò)誤 * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.error("發(fā)生錯(cuò)誤:{},Session ID: {}",error.getMessage(),session.getId()); error.printStackTrace(); } /** * 發(fā)送消息,實(shí)踐表明,每次瀏覽器刷新,session會(huì)發(fā)生變化。 * @param session * @param message */ public static void SendMessage(Session session, String message) { try { // session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId())); session.getBasicRemote().sendText(message); } catch (IOException e) { log.error("發(fā)送消息出錯(cuò):{}", e.getMessage()); e.printStackTrace(); } } /** * 群發(fā)消息 * @param message * @throws IOException */ public static void BroadCastInfo(String message) throws IOException { for (Session session : SessionSet) { if(session.isOpen()){ SendMessage(session, message); } } } /** * 指定Session發(fā)送消息 * @param sessionId * @param message * @throws IOException */ public static void SendMessage(String message,String sessionId) throws IOException { Session session = null; for (Session s : SessionSet) { if(s.getId().equals(sessionId)){ session = s; break; } } if(session!=null){ SendMessage(session, message); } else{ log.warn("沒(méi)有找到你指定ID的會(huì)話:{}",sessionId); } } }
新建一個(gè)html
目前大部分瀏覽器支持WebSocket,比如Chrome, Mozilla,Opera和Safari,在html頁(yè)面進(jìn)行websocket的連接建立、收消息的監(jiān)聽(tīng),頁(yè)面代碼如下:
<html> <head> <meta charset="UTF-8"> <title>websocket測(cè)試</title> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <style type="text/css"> h3,h4{ text-align:center; } </style> </head> <body> <h3>WebSocket測(cè)試,客戶端接收到的消息如下:</h3> <textarea id = "messageId" readonly="readonly" cols="150" rows="30" > </textarea> <script type="text/javascript"> var socket; if (typeof (WebSocket) == "undefined") { console.log("遺憾:您的瀏覽器不支持WebSocket"); } else { console.log("恭喜:您的瀏覽器支持WebSocket"); //實(shí)現(xiàn)化WebSocket對(duì)象 //指定要連接的服務(wù)器地址與端口建立連接 //注意ws、wss使用不同的端口。我使用自簽名的證書(shū)測(cè)試, //無(wú)法使用wss,瀏覽器打開(kāi)WebSocket時(shí)報(bào)錯(cuò) //ws對(duì)應(yīng)http、wss對(duì)應(yīng)https。 socket = new WebSocket("ws://localhost:8080/ws/asset"); //連接打開(kāi)事件 socket.onopen = function() { console.log("Socket 已打開(kāi)"); socket.send("消息發(fā)送測(cè)試(From Client)"); }; //收到消息事件 socket.onmessage = function(msg) { $("#messageId").append(msg.data+ "\n"); console.log(msg.data ); }; //連接關(guān)閉事件 socket.onclose = function() { console.log("Socket已關(guān)閉"); }; //發(fā)生了錯(cuò)誤事件 socket.onerror = function() { alert("Socket發(fā)生了錯(cuò)誤"); } //窗口關(guān)閉時(shí),關(guān)閉連接 window.unload=function() { socket.close(); }; } </script> </body> </html>
三、查看運(yùn)行效果
啟動(dòng)SpringBoot項(xiàng)目
打開(kāi)首頁(yè)
本地瀏覽器打開(kāi)首頁(yè)http://localhost:8080/,出現(xiàn)WebSocket測(cè)試頁(yè)面,同時(shí)后臺(tái)打印連接的日志。
有連接加入,當(dāng)前連接數(shù)為:1,sessionId=0
往客戶端發(fā)送消息
通過(guò)上面日志可以看到客戶端連接連接的sessionId,我測(cè)試時(shí)候sessionId是0,然后瀏覽器訪問(wèn)下面接口即可往客戶端發(fā)送消息。
//參數(shù)說(shuō)明: id:sessionID //參數(shù)說(shuō)明: message:消息內(nèi)容 http://localhost:8080/api/ws/sendOne?id=0&message=你好Java碎碎念
發(fā)送消息動(dòng)圖
到此SpringBoot整合WebSocket的功能已經(jīng)全部實(shí)現(xiàn),有問(wèn)題歡迎留言溝通哦!
完整源碼地址: https://github.com/suisui2019/springboot-study
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
springboot dynamic多數(shù)據(jù)源demo以及常見(jiàn)切換、事務(wù)的問(wèn)題
這篇文章主要介紹了springboot dynamic多數(shù)據(jù)源demo以及常見(jiàn)切換、事務(wù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07java request.getHeader("user-agent")獲取瀏覽器信息的方法
這篇文章主要介紹了java request.getHeader("user-agent")獲取瀏覽器信息的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03Java 中的 BufferedWriter 介紹_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
BufferedWriter 是緩沖字符輸出流。它繼承于Writer。接下來(lái)通過(guò)本文給大家分享Java 中的 BufferedWriter知識(shí),需要的朋友參考下吧2017-05-05Java實(shí)現(xiàn)生成自定義時(shí)長(zhǎng)的靜音音頻
這篇文章主要介紹了如何通過(guò)Java實(shí)現(xiàn)一個(gè)音頻工具類,可以實(shí)現(xiàn)生成一段自定義時(shí)長(zhǎng)(精確到毫秒)的wav音頻。感興趣的小伙伴可以了解一下2022-01-01Apache?Commons?BeanUtils:?JavaBean操作方法
這篇文章主要介紹了Apache?Commons?BeanUtils:?JavaBean操作的藝術(shù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12mybatis源碼解讀之executor包語(yǔ)句處理功能
這篇文章主要介紹了executor包語(yǔ)句處理功能,mybatis中支持三種語(yǔ)句類型,不同語(yǔ)句類型支持的變量符號(hào)不同,下文詳細(xì)內(nèi)容,需要的小伙伴可以參考一下2022-02-02SpringBoot中連接多個(gè)RabbitMQ的方法詳解
這篇文章主要介紹了SpringBoot中連接多個(gè)RabbitMQ的方法詳解,要實(shí)現(xiàn) SpringBoot 連接多個(gè) RabbitMQ,只能自定義重寫(xiě)一些東西,分別配置才可以,下面一起來(lái)走一下試試,需要的朋友可以參考下2023-10-10Java簡(jiǎn)單幾步實(shí)現(xiàn)一個(gè)二叉搜索樹(shù)
二叉樹(shù)包含了根節(jié)點(diǎn),孩子節(jié)點(diǎn),葉節(jié)點(diǎn),每一個(gè)二叉樹(shù)只有一個(gè)根節(jié)點(diǎn),每一個(gè)結(jié)點(diǎn)最多只有兩個(gè)節(jié)點(diǎn),左子樹(shù)的鍵值小于根的鍵值,右子樹(shù)的鍵值大于根的鍵值,下面這篇文章主要給大家介紹了關(guān)于如何在Java中實(shí)現(xiàn)二叉搜索樹(shù)的相關(guān)資料,需要的朋友可以參考下2023-02-02