首先,在springboot項目創建並配置成功的基礎上對websocket進行整合。
1、在pom文件中添加對websocket的依賴
1 <!-- 引入 websocket 依賴類--> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-websocket</artifactId> 5 </dependency>
2、個人習慣是先從後端寫到前端,先寫websocket的配置類吧
1 import org.springframework.stereotype.Component; 2 3 import javax.websocket.*; 4 import javax.websocket.server.ServerEndpoint; 5 import java.io.IOException; 6 import java.util.concurrent.CopyOnWriteArraySet; 7 8 /** 9 * @Name:WebSocket 10 * @Description:WebSocket配置 11 * @Version:V1.0.0 12 * @Author:mYunYu 13 * @Create Date:2018/11/15 14:45 14 */ 15 @Component 16 @ServerEndpoint(value = "/ws/webSocket" , encoders = {EncoderClassVo.class}) 17 public class WebSocket { 18 //每個客戶端都會有相應的session,服務端可以發送相關消息 19 private Session session; 20 21 //J.U.C包下線程安全的類,主要用來存放每個客戶端對應的webSocket連接 22 private static CopyOnWriteArraySet<WebSocket> copyOnWriteArraySet = new CopyOnWriteArraySet<WebSocket>(); 23 24 /** 25 * @Name:onOpen 26 * @Description:打開連接。進入頁面後會自動發請求到此進行連接 27 * @Author:mYunYu 28 * @Create Date:14:46 2018/11/15 29 * @Parameters: 30 * @Return: 31 */ 32 @OnOpen 33 public void onOpen(Session session) { 34 this.session = session; 35 copyOnWriteArraySet.add(this); 36 System.out.println("websocket有新的連接, 總數:"+ copyOnWriteArraySet.size()); 37 38 } 39 40 /** 41 * @Name:onClose 42 * @Description:用戶關閉頁面,即關閉連接 43 * @Author:mYunYu 44 * @Create Date:14:46 2018/11/15 45 * @Parameters: 46 * @Return: 47 */ 48 @OnClose 49 public void onClose() { 50 copyOnWriteArraySet.remove(this); 51 System.out.println("websocket連接斷開, 總數:"+ copyOnWriteArraySet.size()); 52 } 53 54 /** 55 * @Name:onMessage 56 * @Description:測試客戶端發送消息,測試是否聯通 57 * @Author:mYunYu 58 * @Create Date:14:46 2018/11/15 59 * @Parameters: 60 * @Return: 61 */ 62 @OnMessage 63 public void onMessage(String message) { 64 System.out.println("websocket收到客戶端發來的消息:"+message); 65 } 66 67 /** 68 * @Name:onError 69 * @Description:出現錯誤 70 * @Author:mYunYu 71 * @Create Date:14:46 2018/11/15 72 * @Parameters: 73 * @Return: 74 */ 75 @OnError 76 public void onError(Session session, Throwable error) { 77 System.out.println("發生錯誤:" + error.getMessage() + "; sessionId:" + session.getId()); 78 error.printStackTrace(); 79 } 80 81 public void sendMessage(Object object){ 82 //遍歷客戶端 83 for (WebSocket webSocket : copyOnWriteArraySet) { 84 System.out.println("websocket廣播消息:" + object.toString()); 85 try { 86 //服務器主動推送 87 webSocket.session.getBasicRemote().sendObject(object) ; 88 } catch (Exception e) { 89 e.printStackTrace(); 90 } 91 } 92 } 93 94 /** 95 * @Name:sendMessage 96 * @Description:用於發送給客戶端消息(羣發) 97 * @Author:mYunYu 98 * @Create Date:14:46 2018/11/15 99 * @Parameters: 100 * @Return: 101 */ 102 public void sendMessage(String message) { 103 //遍歷客戶端 104 for (WebSocket webSocket : copyOnWriteArraySet) { 105 System.out.println("websocket廣播消息:" + message); 106 try { 107 //服務器主動推送 108 webSocket.session.getBasicRemote().sendText(message); 109 } catch (Exception e) { 110 e.printStackTrace(); 111 } 112 } 113 } 114 115 /** 116 * @Name:sendMessage 117 * @Description:用於發送給指定客戶端消息 118 * @Author:mYunYu 119 * @Create Date:14:47 2018/11/15 120 * @Parameters: 121 * @Return: 122 */ 123 public void sendMessage(String sessionId, String message) throws IOException { 124 Session session = null; 125 WebSocket tempWebSocket = null; 126 for (WebSocket webSocket : copyOnWriteArraySet) { 127 if (webSocket.session.getId().equals(sessionId)) { 128 tempWebSocket = webSocket; 129 session = webSocket.session; 130 break; 131 } 132 } 133 if (session != null) { 134 tempWebSocket.session.getBasicRemote().sendText(message); 135 } else { 136 System.out.println("沒有找到你指定ID的會話:{}"+ "; sessionId:" + sessionId); 137 } 138 } 139 140 /** 141 * 如果使用springboot內置tomcat,需要配置,否則不需要 142 * 143 * @return 144 */ 145 // @Bean 146 // public ServerEndpointExporter serverEndpointExporter() { 147 // return new ServerEndpointExporter(); 148 // } 149 150 151 }
上面類中的紅色註釋的代碼是隻有當springboot項目使用內置tomcat時需要配置(即打成jar包),如果使用外置tomcat則不需要配置(即打成war包)
3、配置編碼器,主要是需要後端向前端發送對象數據,如果只是發送普通的字符串數據的話,就不需要
1 import com.alibaba.fastjson.JSON; 2 import com.xxx.utils.MsgUtil; 3 4 import javax.websocket.EncodeException; 5 import javax.websocket.Encoder; 6 import javax.websocket.EndpointConfig; 7 8 /** 9 * @Name:EncoderClassVo 10 * @Description:編碼器,防止發送對象出錯 11 * @Version:V1.0.0 12 * @Author:mYunYu 13 * @Create Date:2018/11/15 14:43 14 */ 15 public class EncoderClassVo implements Encoder.Text<MsgUtil> { 16 17 @Override 18 public void init(EndpointConfig endpointConfig) { 19 20 } 21 22 @Override 23 public void destroy() { 24 25 } 26 27 @Override 28 public String encode(MsgUtil msgUtil) throws EncodeException { 29 try{ 30 return JSON.toJSONString(msgUtil) ; 31 }catch (Exception e){ 32 e.printStackTrace() ; 33 return null; 34 } 35 } 36 }
4、接下來就是寫controller層了,我這邊demo只是簡單的發送一些隨機的數據,具體信息還需要根據各個項目需要來寫
1 import com.xxx.pojo.User; 2 import com.xxx.utils.MsgUtil; 3 import com.xxx.webSocket.WebSocket; 4 import org.springframework.web.bind.annotation.RequestMapping; 5 import org.springframework.web.bind.annotation.RestController; 6 7 import javax.annotation.Resource; 8 import java.io.IOException; 9 10 /** 11 * @Name:SocketController 12 * @Description:消息發送Controller 13 * @Version:V1.0.0 14 * @Author:mYunYu 15 * @Create Date:2018/11/15 16:44 16 */ 17 @RestController 18 public class SocketController { 19 20 @Resource 21 WebSocket webSocket; 22 23 /** 24 * @Name:helloManyWebSocket 25 * @Description:羣發消息 26 * @Author:mYunYu 27 * @Create Date:16:44 2018/11/15 28 * @Parameters: 29 * @Return: 30 */ 31 @RequestMapping("many") 32 public String helloManyWebSocket(){ 33 34 int i = 1 ; 35 while(i > 0){ 36 i=1+(int)(Math.random()*600) ; 37 User user = new User() ; 38 user.setUserid(i+1) ; 39 user.setUsername(String.valueOf(i) + String.valueOf(i+i)) ; 40 41 //將對象轉爲json對象,併發送到前端 42 MsgUtil msgUtil = MsgUtil.success().addMsg("map", user); 43 webSocket.sendMessage(msgUtil); 44 45 try{ 46 Thread.sleep(1000) ; 47 }catch (Exception e){ 48 e.printStackTrace() ; 49 } 50 } 51 52 return "發送成功"; 53 } 54 55 /** 56 * @Name:helloOneWebSocket 57 * @Description:根據session單個發送消息 58 * @Author:mYunYu 59 * @Create Date:16:44 2018/11/15 60 * @Parameters: 61 * @Return: 62 */ 63 @RequestMapping("one") 64 public String helloOneWebSocket(String sessionId) throws IOException { 65 //向某個人發送消息 66 webSocket.sendMessage(sessionId,"你好~!,單個用戶"); 67 68 return "發送成功"; 69 } 70 71 72 }
5、接下來該在前端寫配置了,我這裏使用的是thymeleaf模板
1 <!DOCTYPE html > 2 <html lang="en" xmlns:th="http://www.thymeleaf.org"> 3 <head> 4 <meta charset="UTF-8"/> 5 <title>Title</title> 6 </head> 7 <body> 8 9 自動連接websocket 10 <script type="text/javascript"> 11 12 var socket; 13 if (typeof (WebSocket) == "undefined") { 14 console.log("遺憾:您的瀏覽器不支持WebSocket"); 15 } else { 16 console.log("恭喜:您的瀏覽器支持WebSocket"); 17 18 //實現化WebSocket對象 19 //指定要連接的服務器地址與端口建立連接 20 //注意ws、wss使用不同的端口。我使用自簽名的證書測試, 21 //無法使用wss,瀏覽器打開WebSocket時報錯 22 //ws對應http、wss對應https。 23 socket = new WebSocket("ws://127.0.0.1:端口號/項目名/ws/webSocket"); 24 //連接打開事件 25 socket.onopen = function() { 26 console.log("Socket 已打開"); 27 socket.send("消息發送測試(From Client)"); 28 }; 29 //收到消息事件 30 socket.onmessage = function(msg) { 31 console.log(msg.data) ; 32 }; 33 //連接關閉事件 34 socket.onclose = function() { 35 console.log("Socket已關閉"); 36 }; 37 //發生了錯誤事件 38 socket.onerror = function() { 39 alert("Socket發生了錯誤"); 40 } 41 42 //窗口關閉時,關閉連接 43 window.unload=function() { 44 socket.close(); 45 }; 46 47 } 48 49 </script> 50 51 52 </body> 53 </html>
6、最後就是測試了,先右擊項目,選擇Run Mavan-->clear install進行項目打包
打包成功之後再啓動外置tomcat來啓動項目
啓動項目成功,在瀏覽器中訪問
按f12,如果出現”Socket已打開“字樣,則表示客戶端連接ok,現在需要使用服務端向客戶端發送消息
再打開另一個瀏覽器,輸入http://localhost:端口號/項目名/many進行訪問,就可以觀察到idea和瀏覽器中已經打印了發送的消息字樣了
上圖是客戶端訪問的瀏覽器所顯示的消息,下圖是服務器端所打印的消息
好了,實現的很成功,接下來就是對發送的數據進行替換就差不多了,哈哈~