Java EE HTML5 WebSocket 示例

在本教程中,我們將藉助於Java EE的WebSocket(服務器端)實現一個HTML5的WebSocket連接。

1. 介紹

HTML5給Web瀏覽器帶來了全雙工TCP連接websocket標準服務器的能力。

換句話說,瀏覽器能夠與服務器建立連接,通過已建立的通信信道來發送和接收數據而不需要由HTTP協議引入額外其他的開銷來實現。

在本教程中我們將在Java EE環境下實現一個簡單的websockect服務器端來和客戶端進行數據交互。

本教程需要以下環境:

  1. Ubuntu 12.04
  2. JDK 1.7.0.21
  3. Glassfish 4.0
: Java EE 7中才引入了WebSocket。
 

2. WebSocket服務器端

讓我們定義一個 Java EE websocket服務器端:

WebSocketTest.java

01 package com.byteslounge.websockets;
02  
03 import java.io.IOException;
04  
05 import javax.websocket.OnClose;
06 import javax.websocket.OnMessage;
07 import javax.websocket.OnOpen;
08 import javax.websocket.Session;
09 import javax.websocket.server.ServerEndpoint;
10  
11 @ServerEndpoint("/websocket")
12 public class WebSocketTest {
13  
14   @OnMessage
15   public voidonMessage(String message, Session session)
16     throws IOException, InterruptedException {
17    
18     // Print the client message for testing purposes
19     System.out.println("Received: " + message);
20    
21     // Send the first message to the client
22     session.getBasicRemote().sendText("This is the first server message");
23    
24     // Send 3 messages to the client every 5 seconds
25     int sentMessages = 0;
26     while(sentMessages < 3){
27       Thread.sleep(5000);
28       session.getBasicRemote().
29         sendText("This is an intermediate server message. Count: "
30           + sentMessages);
31       sentMessages++;
32     }
33    
34     // Send a final message to the client
35     session.getBasicRemote().sendText("This is the last server message");
36   }
37    
38   @OnOpen
39   public void onOpen() {
40     System.out.println("Client connected");
41   }
42  
43   @OnClose
44   public void onClose() {
45     System.out.println("Connection closed");
46   }
47 }
你可能已經注意到我們從 javax.websocket包中引入了一些類。

@ServerEndpoint 註解是一個類層次的註解,它的功能主要是將目前的類定義成一個websocket服務器端。註解的值將被用於監聽用戶連接的終端訪問URL地址。

onOpen 和 onClose 方法分別被@OnOpen@OnClose 所註解。這兩個註解的作用不言自明:他們定義了當一個新用戶連接和斷開的時候所調用的方法。

onMessage 方法被@OnMessage所註解。這個註解定義了當服務器接收到客戶端發送的消息時所調用的方法。注意:這個方法可能包含一個javax.websocket.Session可選參數(在我們的例子裏就是session參數)。如果有這個參數,容器將會把當前發送消息客戶端的連接Session注入進去。

本例中我們僅僅是將客戶端消息內容打印出來,然後首先我們將發送一條開始消息,之後間隔5秒向客戶端發送1條測試消息,共發送3次,最後向客戶端發送最後一條結束消息。

3. 客戶端

現在我們要來寫websocket測試應用的客戶端:

page.html

01 <!DOCTYPE html>
02 <html>
03 <head>
04 <title>Testing websockets</title>
05 </head>
06 <body>
07   <div>
08     <input type="submit" value="Start" onclick="start()" />
09   </div>
10   <div id="messages"></div>
11   <script type="text/javascript">
12     varwebSocket =
13       new WebSocket('ws://localhost:8080/byteslounge/websocket');
14  
15     webSocket.onerror = function(event) {
16       onError(event)
17     };
18  
19     webSocket.onopen = function(event) {
20       onOpen(event)
21     };
22  
23     webSocket.onmessage = function(event) {
24       onMessage(event)
25     };
26  
27     function onMessage(event) {
28       document.getElementById('messages').innerHTML
29         += '<br />' + event.data;
30     }
31  
32     function onOpen(event) {
33       document.getElementById('messages').innerHTML
34         'Connection established';
35     }
36  
37     function onError(event) {
38       alert(event.data);
39     }
40  
41     function start() {
42       webSocket.send('hello');
43       return false;
44     }
45   </script>
46 </body>
47 </html>

這是一個簡單的頁面,包含有JavaScript代碼,這些代碼創建了一個websocket連接到websocket服務器端。

onOpen 我們創建一個連接到服務器的連接時將會調用此方法。

onError 當客戶端-服務器通信發生錯誤時將會調用此方法。

onMessage 當從服務器接收到一個消息時將會調用此方法。在我們的例子中,我們只是將從服務器獲得的消息添加到DOM。

我們連接到websocket 服務器端,使用構造函數 new WebSocket() 而且傳之以端點URL:

ws://localhost:8080/byteslounge/websocket

4. 測試

現在我們可以訪問測試頁面對我們的應用進行測試:

http://localhost:8080/byteslounge/page.html

正如所期望的,我們將看到 Connection established 消息:

http://localhost:8080/byteslounge/page.html

現在只要我們一按按鈕,就會通過此websocket發送初始化報文給服務器,而且接下來會收到發自服務器的測試消息:

服務器發送、客戶端接收的消息

5. WebSockets 握手

客戶端和服務器端TCP連接建立在HTTP協議握手發生之後。通過HTTP流量調試,很容易觀察到握手。客戶端一創建一個 WebSocket實例,就會出現如下請求和服務器端響應: 

注意: 我們只錄入了WebSocket握手所用到的HTTP頭。

請求:

GET /byteslounge/websocket HTTP/1.1 
Connection: Upgrade 
Upgrade: websocket 
Sec-WebSocket-Key: wVlUJ/tu9g6EBZEh51iDvQ==

響應:

HTTP/1.1 101 Web Socket Protocol Handshake 
Upgrade: websocket 
Sec-WebSocket-Accept: 2TNh+0h5gTX019lci6mnvS66PSY=

注意:進行連接需要將通過Upgrade and Upgrade將協議升級到支持websocket HTTP頭的Websocket協議。服務器響應表明請求被接受,協議將轉換到WebSocket協議(HTTP狀態碼101):

HTTP/1.1 101 Web Socket Protocol Handshake

6. 下載源碼

在本頁的末尾有範例源代碼下載鏈接,源碼在Glassfish 4(需要兼容Java EE 7的服務器)上通過測試。
在如下地址下載範例源碼:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章