WebSocket實現Java后台消息推送


1.什么是WebSocket

  WebSocket協議是基於TCP的一種新的網絡協議。它實現了瀏覽器與服務器全雙工(full-duplex)通信——允許服務器主動發送信息給客戶端。

2.實現原理

  在實現websocket連線過程中,需要通過瀏覽器發出websocket連線請求,然后服務器發出回應,這個過程通常稱為“握手” 。在 WebSocket API,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。

                        

3.優點

  在以前的消息推送機制中,用的都是 Ajax 輪詢(polling),在特定的時間間隔由瀏覽器自動發出請求,將服務器的消息主動的拉回來,這種方式是非常消耗資源的,因為它本質還是http請求,而且顯得非常笨拙。而WebSocket 在瀏覽器和服務器完成一個握手的動作,在建立連接之后,服務器可以主動傳送數據給客戶端,客戶端也可以隨時向服務器發送數據。

4.WebSocket和Socket的區別

  1.WebSocket:

    1. websocket通訊的建立階段是依賴於http協議的。最初的握手階段是http協議,握手完成后就切換到websocket協議,並完全與http協議脫離了。

    2. 建立通訊時,也是由客戶端主動發起連接請求,服務端被動監聽。

    3. 通訊一旦建立連接后,通訊就是“全雙工”模式了。也就是說服務端和客戶端都能在任何時間自由得發送數據,非常適合服務端要主動推送實時數據的業務場景。

    4. 交互模式不再是“請求-應答”模式,完全由開發者自行設計通訊協議。

    5. 通信的數據是基於“幀(frame)”的,可以傳輸文本數據,也可以直接傳輸二進制數據,效率高。當然,開發者也就要考慮封包、拆包、編號等技術細節。

  2.Socket:

    1. 服務端監聽通訊,被動提供服務;客戶端主動向服務端發起連接請求,建立起通訊。

    2. 每一次交互都是:客戶端主動發起請求(request),服務端被動應答(response)。

    3. 服務端不能主動向客戶端推送數據。

    4. 通信的數據是基於文本格式的。二進制數據(比如圖片等)要利用base64等手段轉換為文本后才能傳輸。

5.WebSocket客戶端:

var websocket = null;
var host = document.location.host;  
var username = "${loginUsername}"; // 獲得當前登錄人員的userName  
 // alert(username)
//判斷當前瀏覽器是否支持WebSocket  
if ('WebSocket' in window) {  
	alert("瀏覽器支持Websocket")
    websocket = new WebSocket('ws://'+host+'/mm-dorado/webSocket/'+username);  
} else {  
    alert('當前瀏覽器 Not support websocket')  
}  

//連接發生錯誤的回調方法  
websocket.onerror = function() {  
  alert("WebSocket連接發生錯誤")
   setMessageInnerHTML("WebSocket連接發生錯誤");  
};   
  
//連接成功建立的回調方法  
websocket.onopen = function() {
  alert("WebSocket連接成功")  
   setMessageInnerHTML("WebSocket連接成功");  
}  
  
//接收到消息的回調方法  
websocket.onmessage = function(event) {
	alert("接收到消息的回調方法")  
	alert("這是后台推送的消息:"+event.data); 
     websocket.close();
    alert("webSocket已關閉!")
}  
  
//連接關閉的回調方法  
websocket.onclose = function() {  
    setMessageInnerHTML("WebSocket連接關閉");  
}  
  
//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。  
window.onbeforeunload = function() {  
    closeWebSocket();  
}  
  
//關閉WebSocket連接  
function closeWebSocket() {  
    websocket.close();  
}  

//將消息顯示在網頁上
    function setMessageInnerHTML(innerHTML) {
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

  6.WebSocket服務端(java后台):

    1.核心類:
package com.mes.util;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.google.gson.JsonObject;

import net.sf.json.JSONObject;
@ServerEndpoint("/webSocket/{username}")   
	public class WebSocket {  
	    private static int onlineCount = 0;  
	    private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();  
	    private Session session;  
	    private String username;  
	      
	    @OnOpen  
	    public void onOpen(@PathParam("username") String username, Session session) throws IOException {  
	  
	        this.username = username;  
	        this.session = session;  
	          
	        addOnlineCount();  
	        clients.put(username, this); 
	        System.out.println("已連接");
	    }  
	  
	    @OnClose  
	    public void onClose() throws IOException {  
	        clients.remove(username);  
	        subOnlineCount();  
	    }  
	  
	    @OnMessage  
	    public void onMessage(String message) throws IOException {  
	  
	        JSONObject jsonTo = JSONObject.fromObject(message);  
	        String mes = (String) jsonTo.get("message");
	        
	        if (!jsonTo.get("To").equals("All")){  
	            sendMessageTo(mes, jsonTo.get("To").toString());  
	        }else{  
	            sendMessageAll("給所有人");  
	        }  
	    }  
	  
	    @OnError  
	    public void onError(Session session, Throwable error) {  
	        error.printStackTrace();  
	    }  
	  
	    public void sendMessageTo(String message, String To) throws IOException {  
	        // session.getBasicRemote().sendText(message);  
	        //session.getAsyncRemote().sendText(message);  
	        for (WebSocket item : clients.values()) {  
	            if (item.username.equals(To) )  
	                item.session.getAsyncRemote().sendText(message);  
	        }  
	    }  
	      
	    public void sendMessageAll(String message) throws IOException {  
	        for (WebSocket item : clients.values()) {  
	            item.session.getAsyncRemote().sendText(message);  
	        }  
	    }  
	  
	    public static synchronized int getOnlineCount() {  
	        return onlineCount;  
	    }  
	  
	    public static synchronized void addOnlineCount() {  
	        WebSocket.onlineCount++;  
	    }  
	  
	    public static synchronized void subOnlineCount() {  
	        WebSocket.onlineCount--;  
	    }  
	  
	    public static synchronized Map<String, WebSocket> getClients() {  
	        return clients;  
	    }  
}
  2.在自己代碼中的調用:
WebSocket ws = new WebSocket();
JSONObject jo = new JSONObject();
jo.put("message", "這是后台返回的消息!");
jo.put("To",invIO.getIoEmployeeUid());
ws.onMessage(jo.toString());

  7.所需maven依賴:

<!-- webSocket 開始-->
<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>
<!-- webSocket 結束-->

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM