WebSocket技術,是用於服務端與瀏覽器端的基於TCP/IP的會話協議所興起的一項技術 但凡TCP/IP協議都會經過三次握手,而後進行會話數據的傳輸。保證數據的可靠性(在網絡技術發達的今天,這點已經再也不是問題了) 此項技術放棄了之前的須要定時給服務器發送請求。由服務器刷新數據,而後返回給客戶端,這樣大大的減小了服務器的負擔 咱們如何去實現WebSocketjavascript
我用的環境爲 jdk1.7+ Tomcat 7.0.52 服務引用的主要Jar包爲 catalina.jar,websocket-api.jar 全來自tomcat/lib下 服務端代碼以下:html
package com.zx.websocket; import java.io.IOException; import java.util.Collection; import java.util.Iterator; 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.ServerEndpoint; /** * @ServerEndpoint 註解是一個類層次的註解,它的功能主要是將目前的類定義成一個websocket服務器端, * 註解的值將被用於監聽用戶鏈接的終端訪問URL地址,客戶端能夠經過這個URL來鏈接到WebSocket服務器端 */ @ServerEndpoint(value="/singlewebsocket") public class WebSocketSingleTest { //靜態變量,用來記錄當前在線鏈接數。應該把它設計成線程安全的。 private static Integer onlineCount = 0; //concurrent包的線程安全Map,能夠使用Map來存放,其中Key能夠爲用戶標識 private static Map<Session, WebSocketSingleTest> map=new ConcurrentHashMap<Session, WebSocketSingleTest>(); //聲明這是用戶打開鏈接處理的方法 @OnOpen public void OnOpen(Session session) throws IOException { System.out.println("有新用戶連入!session info is :"+session.getId()); synchronized (onlineCount) { addOnlineCount();//在線用戶加1 此方法同步 } map.put(session, this);//添加用戶信息 Collection key=map.keySet(); Iterator it=key.iterator(); String ids=""; while(it.hasNext()){ ids+=((Session)it.next()).getId()+","; } session.getBasicRemote().sendText(ids); } //聲明這是用戶關閉鏈接處理的方法 @OnClose public void OnClose(Session session) { System.out.println("有用戶退出!用戶ID is :"+session.getId()); synchronized (onlineCount) { reduiceOnlineCount();//在線用戶減1 此方法同步 } map.remove(session);//移除用戶信息 } //聲明這是異常處理的方法 @OnError public void onError(Session session, Throwable error){ System.out.println("發生錯誤"); error.printStackTrace(); } //聲明這是用戶發送消息的方法 @OnMessage public void OnMessage(String message,Session session) { System.out.println("來自客戶端的消息:["+message+"]"); /** * 獲取消息後,讀取message獲取傳輸消息的目標人,根據session的Id能夠遍歷Map集合 獲取Map的對應的Socket類 * 而後在由這個Socket類 發送消息 參見sendMessage * 注:目標人消息應該經過Message從前臺傳遞過來,再由後臺遍歷處理 */ } public void sendMessage(Session session,String message) throws IOException { session.getBasicRemote().sendText(message); } public static int getOnlineCount() { return onlineCount; } public static void setOnlineCount(int onlineCount) { WebSocketSingleTest.onlineCount = onlineCount; } public synchronized void addOnlineCount() { WebSocketSingleTest.onlineCount++; } public synchronized void reduiceOnlineCount() { WebSocketSingleTest.onlineCount--; } }
Jsp端主要JS代碼以下:java
<%@ 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/websocket/zxwebsocket"); } 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>
這樣一個消息推送機制就完成了web
其中發佈的時候我碰到的一些問題,在第一次訪問的時候, 服務器後臺會抱一個錯,這個錯是一個類型轉換異常, DefaultInstanceManager cannot be cast to InstanceManager 百度後知道, 在發佈的時候tomcat會將 catalina.jar包加到項目的web-inf下面的lib文件夾下面,這樣這個包就會和tomcat下面的lib下面的catalina.jar 包衝突會報java.lang.ClassCastException 解決方案一:在部署的時候 須要在發佈後的項目WEB-INF/lib下去掉catalina.jar和websocket-api.jar 解決方案二:修改了tomcat裏的context.xml文件,在context 元素下添加<Loader delegate="true" />後端