1. 程式人生 > >Java WebSocket

Java WebSocket

cep end 方法 user not trace ble https 註解

本示例的目的,就是通過webSocket向客戶端(瀏覽器端)發送消息. 一、什麽是WebSocket   WebSocket協議是基於TCP的一種新的網絡協議。它實現了瀏覽器與服務器全雙工(full-duplex)通信——允許服務器主動發送信息給客戶端。 WebSocket通信協議於2011年被IETF定為標準RFC 6455,並被RFC7936所補充規範。 二、通過Java代碼實現從服務端發消息給客戶端 三、環境說明   java1.7、apache-tomcat-7.0.78、maven   依賴
  <dependency>
  <groupId>javax</groupId>
  <artifactId>javaee-api</artifactId>
  <version>7.0</version>
  <scope>provided</scope>
  </dependency>
四、代碼
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @ServerEndpoint 註解是一個類層次的註解,它的功能主要是將目前的類定義成一個websocket服務器端,
 * 註解的值將被用於監聽用戶連接的終端訪問URL地址,客戶端可以通過這個URL來連接到WebSocket服務器端
 
*/ @ServerEndpoint("/websocket/{userId}") public class NoticeWebSocket { //靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。 private static int onlineCount = 0; //concurrent包的線程安全map,用來存放每個客戶端對應的NoticeWebSocket對象 private static ConcurrentMap<String, NoticeWebSocket> webSocketSet = new ConcurrentHashMap<String, NoticeWebSocket>();
//與某個客戶端的連接會話,需要通過它來給客戶端發送數據 private Session session; /** * 連接建立成功調用的方法 * * @param session 可選的參數。session為與某個客戶端的連接會話,需要通過它來給客戶端發送數據 */ @OnOpen public void onOpen(@PathParam(value = "userId") String userId, Session session) { this.session = session; webSocketSet.put(userId, this); //加入set中 addOnlineCount(); //在線數加1 System.out.println("有新連接加入!當前在線人數為" + getOnlineCount()); } /** * 連接關閉調用的方法 */ @OnClose public void onClose(@PathParam(value = "userId") String userId) { webSocketSet.remove(userId); //從set中刪除 subOnlineCount(); //在線數減1 System.out.println("有一連接關閉!當前在線人數為" + getOnlineCount()); } /** * 收到客戶端消息後調用的方法 * * @param message 客戶端發送過來的消息 * @param session 可選的參數 */ @OnMessage public void onMessage(String message, Session session) { System.out.println("來自客戶端的消息:" + message); //群發消息 for (Map.Entry entry : webSocketSet.entrySet()) { try { NoticeWebSocket item = (NoticeWebSocket) entry.getValue(); item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); continue; } } } /** * 發生錯誤時調用 * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { System.out.println("發生錯誤"); error.printStackTrace(); } /** * 這個方法與上面幾個方法不一樣。沒有用註解,是根據自己需要添加的方法。 * * @param message * @throws IOException */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { NoticeWebSocket.onlineCount++; } public static synchronized void subOnlineCount() { NoticeWebSocket.onlineCount--; } public static ConcurrentMap<String, NoticeWebSocket> getWebSocketSet() { return webSocketSet; } public static void setWebSocketSet(ConcurrentMap<String, NoticeWebSocket> webSocketSet) { NoticeWebSocket.webSocketSet = webSocketSet; } }

頁面Js

var websocket = null;
    //判斷當前瀏覽器是否支持WebSocket
    if (‘WebSocket‘ in window) {
        websocket = new WebSocket("ws://localhost:8080/websocket/xxx");
    }
    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) {
        console.log(innerHTML);
    }

    //關閉WebSocket連接
    function closeWebSocket() {
        websocket.close();
    }

    //發送消息
    function send() {
        var message = "牛。。";
        websocket.send(message);
    }

測試

我是用了SpringMvc 寫了一個Controller

/**
     * 發送消息給當前登錄人 TEST
     *
     * @return
     */
    @RequestMapping(value = "/free/sendMessageTest", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> sendMessageTest(String userId) {
        Map<String, Object> map = new HashMap<String, Object>();
        ConcurrentMap<String, NoticeWebSocket> noticeWebSockets = NoticeWebSocket.getWebSocketSet();
        try {
            map.put("status", 0);
            NoticeWebSocket noticeWebSocket = noticeWebSockets.get(userId);
            if (null != noticeWebSocket) {
                noticeWebSocket.sendMessage("牛逼Class UserId=" + userId);
            }
        } catch (IOException e) {
            e.printStackTrace();
            map.put("status", -1);
        }
        return map;
    }

說明

websocket = new WebSocket("ws://localhost:8080/websocket/xxx"); xxx 代表一個用戶唯一標識,當頁面加載這段Js時會和服務端建立連接調用後端onOpen(String userId)方法會把"xxx"
傳到後臺去,然後用map保存,userId 就是key,登錄的session 就是value。(如果有多個頁面訪問就會有多個session),我這裏之所有用ConcurrentMap 是因為它是線程安全的。

Java WebSocket