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客戶端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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.核心類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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.在自己代碼中的調用:
1
2
3
4
5
WebSocket ws =  new  WebSocket();
JSONObject jo =  new  JSONObject();
jo.put( "message" "這是后台返回的消息!" );
jo.put( "To" ,invIO.getIoEmployeeUid());
ws.onMessage(jo.toString());

  7.所需maven依賴:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 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