重點前端
一、JAVA內的WebSocket是在Java jar7.0以後才能使用的。java
二、須要在JavaServer項目lib目錄下引入 javaee-api-7.0 包web
|前端代碼後端
|後端JAVA代碼api
package websocketPro;數組
import javax.websocket.OnClose;服務器
import javax.websocket.OnMessage;websocket
import javax.websocket.OnOpen;session
import javax.websocket.Session;socket
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashSet;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* writer: holien Time: 2017-08-01 13:00 Intent: webSocket服務器
*/
@ServerEndpoint("/webSocket/ChatRoom/{roomName}")//這裏是你請求的生成的房間服務器路徑 roomName是前端發來的 roomName名字
public class ChatRoom {
private static final Map> rooms = new ConcurrentHashMap();
@OnOpen //session 是可選的參數,session爲與某個客戶端的鏈接會話,須要經過它來給客戶端發送數據
public void connect(@PathParam("roomName") String roomName, Session session) throws Exception {
if (!rooms.containsKey(roomName)) {
Set room = new HashSet<>();
room.add(session);
rooms.put(roomName, room);
} else {
rooms.get(roomName).add(session);
}
System.out.println("創建鏈接 !");
}
@OnClose
public void disConnect(@PathParam("roomName") String roomName, Session session) {
rooms.get(roomName).remove(session);
System.out.println("斷開鏈接!");
}
@OnMessage
public void receiveMsg(@PathParam("roomName") String roomName, String msg, Session session) throws Exception {
System.out.println(msg);
broadcast(roomName, msg);
}
// 按照房間名進行廣播
public static void broadcast(String roomName, String msg) throws Exception {
for (Session session : rooms.get(roomName)) {
session.getAsyncRemote().sendText(msg);
}
}
}
|JAVA服務器目錄結構
Tip:下面簡單的解釋一下每一個函數及其方法的含義和關聯。
全部WebSocket項目雙向通訊的創建,都須要前端先發送給後端一個請求,而且握手成功以後才能進行通訊 就和打電話一個道理。
webSocket = new WebSocket(url);
上面這個就是前端JS建立一個WebSocket對象 而且發送給後端(URL地址的服務器)一個通訊請求 你正在向一我的打電話,而且等他接電話
@ServerEndpoint("/webSocket/ChatRoom/{roomName}")
var url = "ws://172.16.245.232:8080/WebsocketPro/webSocket/mainBlock/" + roomName;
後端java這個註釋標記了當前這個Java文件的服務器訪問地址和前端的請求的地址是一致的。
前端定義 roomName 的名稱會被後端的 {roomName} 讀取到
以前 前端的roomName定義爲 MainBlock
因此在請求以後後端註釋內的訪問路徑就變成了
/webSocket/ChatRoom/MainBlock
private static final Map> rooms = new ConcurrentHashMap();
@OnOpen
public void connect(@PathParam("roomName") String roomName, Session session) throws Exception {
if (!rooms.containsKey(roomName)) {
Set room = new HashSet<>(); //建立Hash數組 的數理化對象
room.add(session); //把session對象 即用戶對象 添加到Hash對象裏
rooms.put(roomName, room); //而且根據房間名添加用戶組成的 Hash對象 這裏就獲取了一個用戶集
} else {
rooms.get(roomName).add(session); //獲取對應房間的 用戶集
}鄭州較好的婦科醫院 http://www.kd0371.com/
System.out.println("創建鏈接 !");
}
關於 ConcurrentHashMap 參考ConcurrentHashMap
此時在申請以後會被後端的 @OnOpen註釋下的方法接收到
這個時候底層WebSocket會進行和前端的握手協議 咱們是看不到的
諾訪問正常而且握手成功,則服務器會自動調用這個鏈接方法
此時底層會向服務器發送成功握手的協議
而且前端也會調用下面這個定義的的方法
webSocket.onopen = function () {
console.log("和服務器的握手鍊接創建...(握手)")
};
到這裏爲止 前端和後端創建了一個理論上永久的通訊協議,只要其中一方不要斷開鏈接。 你成功和他打通了電話
|開始交流
webSocket.send(msg);
咱們前端調用了WebSocket對象的 send() 方法 傳入要發送給後臺的消息
封裝要發送到服務端的數據通常來講JSON比較好
@OnMessage
public void receiveMsg(@PathParam("roomName") String roomName, String msg, Session session) throws Exception {
System.out.println(msg);
broadcast(roomName, msg);
}
傳入的消息就會被後臺的 @OnMessage 標記的方法接收
@PathParam(「roomName」) String roomName
這句話的意思就是以前標記的 /webSocket/ChatRoom/{roomName} 裏的 roomName 的值
String msg
這個參數就是前臺發送的消息。 Session session 這個參數在代碼中說明了就不重複解釋
在接收到消息以後就調用這個這個函數內的一個完美自定義的方法 broadcast()
public static void broadcast(String roomName, String msg) throws Exception {
for (Session session : rooms.get(roomName)) {
session.getAsyncRemote().sendText(msg);
}
}
這個方法調用了 session 對象裏的 getAsyncRemote() 方法的 sendText(msg)
用來向以前封裝的全部對象( rooms )廣播消息
webSocket.onmessage = function (evt) {
var Data = JSON.parse(evt.data)
};
接收到廣播消息以後,前端調用了 WebSocket對象的 onmessage 方法
這裏的 evt 參數就是廣播的消息 可是後端傳過來的是一個對象
咱們要調用這個對象的 evt.data 方法 若是是Json數據 就把它轉換成咱們js能識別的對象
到這裏爲止來就完成了消息的交流。
要斷開請求的話,就調用 webSocket.close() 方法 ,這個時候
後臺就會自動調用 下面這個方法
@OnClose
public void disConnect(@PathParam("roomName") String roomName, Session session) {
System.out.println("斷開鏈接!");
}
同時響應到前端 ,調用下面這個方法
webSocket.onclose = function () {
console.log("和服務器的握手鍊接已關閉...(分手)")
webSocket = null;
};
到這裏來位置完成了WebSocket 完整的雙向通訊。