您好,登錄后才能下訂單哦!
本篇文章為大家展示了Springboot整合Websocket如何實現(xiàn)后端向前端主動推送消息,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
在手機上相信都有來自服務器的推送消息,比如一些及時的新聞信息,這篇文章主要就是實現(xiàn)這個功能,只演示一個基本的案例。使用的是websocket技術(shù)。
tWebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。它實現(xiàn)了客戶端與服務器全雙工通信,學過計算機網(wǎng)絡(luò)都知道,既然是全雙工,就說明了服務器可以主動發(fā)送信息給客戶端。這與我們的推送技術(shù)或者是多人在線聊天的功能不謀而合。
為什么不使用HTTP 協(xié)議呢?這是因為HTTP是單工通信,通信只能由客戶端發(fā)起,客戶端請求一下,服務器處理一下,這就太麻煩了。于是websocket應運而生。
下面我們就直接開始使用Springboot開始整合。以下案例都在我自己的電腦上測試成功,你可以根據(jù)自己的功能進行修改即可。
Idea 2018專業(yè)版(已破解)
Maven 4.0.0
SpringBoot 2.2.2
websocket 2.1.3
jdk 1.8
下面我們新建一個普通的Springboot項目。
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>2.1.3.RELEASE</version> </dependency> </dependencies>
一句話:server.port=8081
1@Configuration 2public class WebSocketConfig { 3 @Bean 4 public ServerEndpointExporter serverEndpointExporter() { 5 return new ServerEndpointExporter(); 6 } 7}
@ServerEndpoint("/websocket/{sid}") @Component public class WebSocketServer { static Log log= LogFactory.getLog(WebSocketServer.class); //靜態(tài)變量,用來記錄當前在線連接數(shù)。應該把它設(shè)計成線程安全的。 private static int onlineCount = 0; //concurrent包的線程安全Set,用來存放每個客戶端對應的MyWebSocket對象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>(); //與某個客戶端的連接會話,需要通過它來給客戶端發(fā)送數(shù)據(jù) private Session session; //接收sid private String sid=""; /** * 連接建立成功調(diào)用的方法 */ @OnOpen public void onOpen(Session session,@PathParam("sid") String sid) { this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在線數(shù)加1 log.info("有新窗口開始監(jiān)聽:"+sid+",當前在線人數(shù)為" + getOnlineCount()); this.sid=sid; try { sendMessage("連接成功"); } catch (IOException e) { log.error("websocket IO異常"); } } /** * 連接關(guān)閉調(diào)用的方法 */ @OnClose public void onClose() { webSocketSet.remove(this); //從set中刪除 subOnlineCount(); //在線數(shù)減1 log.info("有一連接關(guān)閉!當前在線人數(shù)為" + getOnlineCount()); } /** * 收到客戶端消息后調(diào)用的方法 * @param message 客戶端發(fā)送過來的消息 */ @OnMessage public void onMessage(String message, Session session) { log.info("收到來自窗口"+sid+"的信息:"+message); //群發(fā)消息 for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } @OnError public void onError(Session session, Throwable error) { log.error("發(fā)生錯誤"); error.printStackTrace(); } //實現(xiàn)服務器主動推送 public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } //群發(fā)自定義消息 public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException { log.info("推送消息到窗口"+sid+",推送內(nèi)容:"+message); for (WebSocketServer item : webSocketSet) { try { //這里可以設(shè)定只推送給這個sid的,為null則全部推送 if(sid==null) { item.sendMessage(message); }else if(item.sid.equals(sid)){ item.sendMessage(message); } } catch (IOException e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; }
@Controller public class MyController { //頁面請求 @GetMapping("/socket/{cid}") public ModelAndView socket(@PathVariable String cid) { ModelAndView mav=new ModelAndView("/socket"); mav.addObject("cid", cid); return mav; } //推送數(shù)據(jù)接口 @ResponseBody @RequestMapping("/socket/push/{cid}") public String pushToWeb(@PathVariable String cid,String message) { try { WebSocketServer.sendInfo(message,cid); } catch (IOException e) { e.printStackTrace(); return "推送失敗"; } return "發(fā)送成功"; } }}
<html> <head> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <script type="text/javascript"> var socket; if (typeof (WebSocket) == "undefined") { console.log("您的瀏覽器不支持WebSocket"); } else { console.log("您的瀏覽器支持WebSocket"); //實現(xiàn)化WebSocket對象,指定要連接的服務器地址與端口 建立連接 socket = new WebSocket("ws://localhost:8081/websocket/1"); //打開事件 socket.onopen = function () { console.log("Socket 已打開"); socket.send("這是來自客戶端的消息" + location.href + new Date()); }; //獲得消息事件 socket.onmessage = function (msg) { console.log(msg.data); }; //關(guān)閉事件 socket.onclose = function () { console.log("Socket已關(guān)閉"); }; //發(fā)生了錯誤事件 socket.onerror = function () { alert("Socket發(fā)生了錯誤"); } } </script> </head> </html>
現(xiàn)在開發(fā)服務器和網(wǎng)頁就可以看到效果了。一般情況下Springboot2+Netty+Websocket的組合方式更加的常用一下。這個只是給出了一個基本的案例,你可以根據(jù)自己的需求進行更改。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。