WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議。
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。
在 WebSocket API 中,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。
現在,很多網站為了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然后由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源。
HTML5 定義的 WebSocket 協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。
詳細的WebSocket介紹請參考菜鳥教程WebSocket
因為近期所使用的技術棧為VUE和SpringBoot,因此此文章所用技術環境也為VUE以及SpringBoot下。
建議先在后端(SpringBoot)配置好WebSocket。
maven依賴(因為我的SpringBoot項目為2.0以上,會自動選擇最優版本,因此此處沒有帶上版本號):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
WebSocket配置類:
@Configuration
public class WebSocketConfig {
/**
* 注入ServerEndpointExporter,
* 這個bean會自動注冊使用了@ServerEndpoint注解聲明的Websocket endpoint
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
WebSocket操作類:
WebSocket的向用戶推送可以為向所有用戶推送以及單點推送
@Component
@ServerEndpoint("/websocket/{shopId}")
//此注解相當於設置訪問URL
public class WebSocket {
private Session session;
private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();
private static Map<String,Session> sessionPool = new HashMap<String,Session>();
@OnOpen
public void onOpen(Session session, @PathParam(value="shopId")String shopId) {
this.session = session;
webSockets.add(this);
sessionPool.put(shopId, session);
System.out.println("【websocket消息】有新的連接,總數為:"+webSockets.size());
}
@OnClose
public void onClose() {
webSockets.remove(this);
System.out.println("【websocket消息】連接斷開,總數為:"+webSockets.size());
}
@OnMessage
public void onMessage(String message) {
System.out.println("【websocket消息】收到客戶端消息:"+message);
}
// 此為廣播消息
public void sendAllMessage(String message) {
for(WebSocket webSocket : webSockets) {
System.out.println("【websocket消息】廣播消息:"+message);
try {
webSocket.session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 此為單點消息
public void sendOneMessage(String shopId, String message) {
Session session = sessionPool.get(shopId);
if (session != null) {
try {
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
在Controller中使用
@RestController
@RequestMapping("api")
public class TestController {
@Autowired
private WebSocket webSocket;
@RequestMapping("/sendAllWebSocket")
public String test() {
webSocket.sendAllMessage("清晨起來打開窗,心情美美噠~");
return "websocket群體發送!";
}
@RequestMapping("/sendOneWebSocket")
public String sendOneWebSocket() {
webSocket.sendOneMessage("DPS007", "只要你乖給你買條gai!");
return "websocket單人發送";
}
}
在前端中(VUE)使用WebSocket
當然不在vue中使用也是一樣的,只不過要注意的是WebSocket在普通js中如何創建以及銷毀
<script>
export default {
data() {
return {
shopId:''
}
},
created() { // 頁面創建生命周期函數
this.initWebSocket()
},
destroyed: function () { // 離開頁面生命周期函數
this.websocketclose();
},
methods: {
collapse: function(){
this.isCollapse = !this.isCollapse;
if (this.isCollapse) {
this.iconClass = "cebianlanzhankai";
} else{
this.iconClass = "cebianlanshouhui";
}
},
initWebSocket: function () {
// WebSocket與普通的請求所用協議有所不同,ws等同於http,wss等同於https
this.websock = new WebSocket("ws://localhost:8046/websocket/DPS007");
this.websock.onopen = this.websocketonopen;
this.websock.onerror = this.websocketonerror;
this.websock.onmessage = this.websocketonmessage;
this.websock.onclose = this.websocketclose;
},
websocketonopen: function () {
console.log("WebSocket連接成功");
},
websocketonerror: function (e) {
console.log("WebSocket連接發生錯誤");
},
websocketonmessage: function (e) {
var da = JSON.parse(e.data);
console.log(da);
this.message = da;
},
websocketclose: function (e) {
console.log("connection closed (" + e.code + ")");
}
}
}
</script>