WebSocket 協議本質上是一個基於 TCP 的協議。爲了創建一個 WebSocket 鏈接,客戶端瀏覽器首先要向服務器發起一個 HTTP 請求,這個請求和一般的 HTTP 請求不一樣,包含了一些附加頭信息,其中附加頭信息」Upgrade: WebSocket」代表這是一個申請協議升級的 HTTP 請求,服務器端解析這些附加的頭信息而後產生應答信息返回給客戶端,客戶端和服務器端的 WebSocket 鏈接就創建起來了,雙方就能夠經過這個鏈接通道自由的傳遞信息,而且這個鏈接會持續存在直到客戶端或者服務器端的某一方主動的關閉鏈接。html
在項目中,常規都是前端向後端發送請求後,才能獲取到後端的數據。可是在一些及時消息的處理上,這樣的處理效率有些捉襟見肘;在以往得到即時數據時,比較low的方案就是ajax輪詢查詢;或者可使用socket的長鏈接;可是這些在實際的操做上都比較消耗資源;而websocket在這方面有效的解決這個問題--WebSocket協議是基於TCP的一種新的網絡協議。它實現了瀏覽器與服務器全雙工(full-duplex)通訊——容許服務器主動發送信息給客戶端,客戶端接收到消息可即時對消息進行處理。前端
服務端(Java)java
package org.meal.controller;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/websockets")
public class WebscoketsController extends HttpServlet{
//concurrent包的線程安全Set,用來存放每一個客戶端對應的MyWebSocket對象。若要實現服務端與單一客戶端通訊的話,可使用Map來存放,其中Key能夠爲用戶標識
private static CopyOnWriteArraySet<WebscoketsController> webSocketSet = new CopyOnWriteArraySet<WebscoketsController>();
//這個session不是Httpsession,至關於用戶的惟一標識,用它進行與指定用戶通信
private javax.websocket.Session session=null;
public void doGet(HttpServletRequest request, HttpServletResponse response,long deskId,long shopid) throws ServletException,IOException {
//發送更新信號
sendMessage(deskId,shopid);
//response.sendRedirect("http://localhost:8080");
}
public void doPost(HttpServletRequest request,HttpServletResponse reponse) throws ServletException, IOException {
doGet(request,reponse);
}
/**
* @OnOpen allows us to intercept the creation of a new session.
* The session class allows us to send data to the user.
* In the method onOpen, we'll let the user know that the handshake was * successful. * 創建websocket鏈接時調用 */ @OnOpen public void onOpen(Session session){ System.out.println("Session " + session.getId() + " has opened a connection"); try { this.session=session; webSocketSet.add(this); //加入set中 session.getBasicRemote().sendText("Connection Established"); } catch (IOException ex) { ex.printStackTrace(); } } /** * When a user sends a message to the server, this method will intercept the message * and allow us to react to it. For now the message is read as a String. * 接收到客戶端消息時使用,這個例子裏沒用 */ @OnMessage public void onMessage(String message, Session session){ System.out.println("Message from " + session.getId() + ": " + message); } /** * The user closes the connection. * * Note: you can't send messages to the client from this method
* 關閉鏈接時調用
*/
@OnClose
public void onClose(Session session){
webSocketSet.remove(this); //從set中刪除
System.out.println("Session " +session.getId()+" has closed!");
}
/**
* 注意: OnError() 只能出現一次. 其中的參數都是可選的。
* @param session
* @param t
*/
@OnError
public void onError(Session session, Throwable t) {
t.printStackTrace();
}
/**
* 這個方法與上面幾個方法不同。沒有用註解,是根據本身須要添加的方法。
* @throws IOException
* 發送自定義信號,「1」表示告訴前臺,數據庫發生改變了,須要刷新
*/
public void sendMessage(long deskId,long shopid) throws IOException{
String id=String.valueOf(deskId);
String shop=String.valueOf(shopid);
String ids=id+","+shop;
//羣發消息
for(WebscoketsController item: webSocketSet){
try {
item.session.getBasicRemote().sendText(ids);
} catch (IOException e) {
e.printStackTrace();
continue;
}
}
}
}
//在傳送消息時,須要調用webscoket的doget函數
WebscoketsController controller2 = new WebscoketsController();
try {
controller2.doGet(request, response, list.get(list.size()-1).getDeskId(), shopId);
} catch (ServletException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
複製代碼
客戶端(VUE)react
created () {
this.initWebSocket()
},
methods: {
// weosocket
initWebSocket(){ //初始化weosocket
const wsuri = "ws://localhost:8080";
this.websock = new WebSocket(wsuri);
this.websock.onmessage = this.websocketonmessage;
this.websock.onopen = this.websocketonopen;
this.websock.onerror = this.websocketonerror;
this.websock.onclose = this.websocketclose;
},
websocketonopen(){ //鏈接創建以後執行send方法發送數據
console.log('send')
this.webEach('連接成功')
},
websocket(){//鏈接創建失敗重連
console.log('重連')
this.initWebSocket();
},
websocketonmessage(e){ //數據接收
console.log('數據接收')
console.log(e)
this.webEach(e.data)
},
websocketsend(Data){//數據發送
console.log('數據發送')
},
websocketclose(e){//關閉
console.log('斷開鏈接',e);
}
<!--在頁面中展現所獲取的數據-->
webEach (data) {
console.log(data)
}
}
複製代碼