現不少網站爲了實現即時通信,所用的技術都是輪詢(polling)。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發javascript
出HTTP request,而後由服務器返回最新的數據給客服端的瀏覽器。這種傳統的HTTP request 的模式帶來很明顯的缺點 – 瀏html
覽器須要不斷的向服務器發出請求,然而HTTP request 的header是很是長的,裏面包含的數據可能只是一個很小的值,這樣會佔java
用不少的帶寬。WebSocket提供了一個受歡迎的技術,以替代咱們過去幾年一直在用的Ajax技術。web
1、什麼是WebSocket API?後端
WebSocket API是下一代客戶端-服務器的異步通訊方法。該通訊取代了單個的TCP套接字,使用ws或wss協議,可用於任意的api
客戶端和服務器程序。WebSocket目前由W3C進行標準化。WebSocket已經受到Firefox 四、Chrome 四、Opera 10.70以及Safari 5等跨域
瀏覽器的支持。瀏覽器
WebSocket API最偉大之處在於服務器和客戶端能夠在給定的時間範圍內的任意時刻,相互推送信息。WebSocket並不限於以tomcat
Ajax(或XHR)方式通訊,由於Ajax技術須要客戶端發起請求,而WebSocket服務器和客戶端能夠彼此相互推送信息;XHR受到域安全
的限制,而WebSocket容許跨域通訊。
Ajax技術很聰明的一點是沒有設計要使用的方式。WebSocket爲指定目標建立,用於雙向推送消息。
那麼我就開始我在項目中對websocket的使用。這裏我建立了一個基於maven 的web Project
基於J2EE7的jar以及websocket的核心api。websocket必須基於tomcat7.4以上版本,這裏使用了tomcat8
只須要一個 WebSocketTest.java 和 一個 index.jsp文件便可實現:
1 package com.cn.zym.websocket; 2 3 import java.io.IOException; 4 import java.util.concurrent.CopyOnWriteArraySet; 5 6 import javax.websocket.OnClose; 7 import javax.websocket.OnMessage; 8 import javax.websocket.OnOpen; 9 import javax.websocket.OnError; 10 import javax.websocket.server.ServerEndpoint; 11 12 /** 13 * @ServerEndpoint 註解是一個類層次的註解,它的功能主要是將目前的類定義成一個websocket服務器端, 14 * 註解的值將被用於監聽用戶鏈接的終端訪問URL地址,客戶端能夠經過這個URL來鏈接到WebSocket服務器端 15 */ 16 @ServerEndpoint("/websocket") 17 public class WebSocketTest { 18 //靜態變量,用來記錄當前在線鏈接數。應該把它設計成線程安全的。 19 private static int onlineCount = 0; 20 21 //concurrent包的線程安全Set,用來存放每一個客戶端對應的MyWebSocket對象。 22 // 若要實現服務端與單一客戶端通訊的話,可使用Map來存放,其中Key能夠爲用戶標識 23 private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>(); 24 25 //與某個客戶端的鏈接會話,須要經過它來給客戶端發送數據 26 private Session session; 27 28 /** 29 * 鏈接創建成功調用的方法 30 * @param session 可選的參數。session爲與某個客戶端的鏈接會話,須要經過它來給客戶端發送數據 31 */ 32 @OnOpen 33 public void onOpen(Session session){ 34 this.session = session; 35 webSocketSet.add(this); //加入set中 36 addOnlineCount(); //在線數加1 37 System.out.println("有新鏈接加入!當前在線人數爲" + getOnlineCount()); 38 } 39 40 /** 41 * 鏈接關閉調用的方法 42 */ 43 @OnClose 44 public void onClose(){ 45 webSocketSet.remove(this); //從set中刪除 46 subOnlineCount(); //在線數減1 47 System.out.println("有一鏈接關閉!當前在線人數爲" + getOnlineCount()); 48 } 49 50 /** 51 * 收到客戶端消息後調用的方法 52 * @param message 客戶端發送過來的消息 53 * @param session 可選的參數 54 */ 55 @OnMessage 56 public void onMessage(String message, Session session) { 57 System.out.println("來自客戶端的消息:" + message); 58 //羣發消息 59 for(WebSocketTest item: webSocketSet){ 60 61 try { 62 item.sendMessage(message); 63 } catch (IOException e) { 64 e.printStackTrace(); 65 continue; 66 } 67 } 68 } 69 70 /** 71 * 發生錯誤時調用 72 * @param session 73 * @param error 74 */ 75 @OnError 76 public void onError(Session session, Throwable error){ 77 System.out.println("發生錯誤"); 78 error.printStackTrace(); 79 } 80 81 /** 82 * 這個方法與上面幾個方法不同。沒有用註解,是根據本身須要添加的方法。 83 * @param message 84 * @throws IOException 85 */ 86 public void sendMessage(String message) throws IOException{ 87 this.session.getBasicRemote().sendText(message); 88 //this.session.getAsyncRemote().sendText(message); 89 } 90 91 public static synchronized int getOnlineCount() { 92 return onlineCount; 93 } 94 95 public static synchronized void addOnlineCount() { 96 WebSocketTest.onlineCount++; 97 } 98 99 public static synchronized void subOnlineCount() { 100 WebSocketTest.onlineCount--; 101 } 102 }
須要注意一點,在建立WebSocket實例的時候改地址目前的拼接方式爲:ws://localhost:8080/設置好的項目訪問規則/@ServerEndpoint註解的值
批註:
<%@ page language="java" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <title>Java後端WebSocket的Tomcat實現</title> </head> <body> Welcome<br/><input id="text" type="text"/> <button onclick="send()">發送消息</button> <hr/> <button onclick="closeWebSocket()">關閉WebSocket鏈接</button> <hr/> <div id="message"></div> </body> <script type="text/javascript"> var websocket = null; //判斷當前瀏覽器是否支持WebSocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:8080/jws/websocket"); //websocket = new WebSocket("ws://echo.websocket.org", ["com.kaazing.echo","example.imaginary.protocol"]) } else { alert('當前瀏覽器 Not support websocket') } //鏈接發生錯誤的回調方法 websocket.onerror = function () { setMessageInnerHTML("WebSocket鏈接發生錯誤"); }; //鏈接成功創建的回調方法 websocket.onopen = function () { setMessageInnerHTML("WebSocket鏈接成功"); } //接收到消息的回調方法 websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //鏈接關閉的回調方法 websocket.onclose = function () { setMessageInnerHTML("WebSocket鏈接關閉"); } //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket鏈接,防止鏈接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function () { closeWebSocket(); } //將消息顯示在網頁上 function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //關閉WebSocket鏈接 function closeWebSocket() { websocket.close(); } //發送消息 function send() { var message = document.getElementById('text').value; websocket.send(message); } </script> </html>
學習筆記,效果就不演示了,貼上demo下載:
連接:http://pan.baidu.com/s/1kUW6hVL 密碼:a6ag
具體websocket API參考:http://www.cnblogs.com/Leo_wl/p/5377767.html