· JS-前端代碼.
var websocket;//websocket實(shí)例
var lockReconnect = false;//避免重復(fù)連接
var userno="123";
var wsUrl = "ws://localhost:8080/test/websocket/"+userno;
function createWebSocket(url) {
try {
websocket = new WebSocket(url);
initEventHandle();
} catch (e) {
reconnect(url);
}
}
function initEventHandle() {
websocket.onclose = function () {
console.log("WebSocket連接已經(jīng)關(guān)閉");
reconnect(wsUrl);
};
websocket.onerror = function () {
console.log("WebSocket連接發(fā)生錯(cuò)誤");
reconnect(wsUrl);
};
websocket.onopen = function () {
console.log("WebSocket連接已經(jīng)成功");
//心跳檢測重置
heartCheck.reset().start();
};
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
//如果獲取到消息,心跳檢測重置
//拿到任何消息都說明當(dāng)前連接是正常的
heartCheck.reset().start();
}
}
//重新連接webSocket
function reconnect(url) {
if(lockReconnect) return;
lockReconnect = true;
//沒連接上會(huì)一直重連卓鹿,設(shè)置延遲避免請(qǐng)求過多
setTimeout(function () {
createWebSocket(url);
lockReconnect = false;
}, 2000);
}
//心跳檢測
var heartCheck = {
timeout: 60000,//60秒
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function(){
var self = this;
this.timeoutObj = setTimeout(function(){
//這里發(fā)送一個(gè)心跳,后端收到后周瞎,返回一個(gè)心跳消息,
//onmessage拿到返回的心跳就說明連接正常
websocket.send("HeartBeat");
self.serverTimeoutObj = setTimeout(function(){//如果超過一定時(shí)間還沒重置胁黑,說明后端主動(dòng)斷開了
websocket.close();//如果onclose會(huì)執(zhí)行reconnect职烧,我們執(zhí)行ws.close()就行了.如果直接執(zhí)行reconnect 會(huì)觸發(fā)onclose導(dǎo)致重連兩次
}, self.timeout)
}, this.timeout)
}
}
//判斷當(dāng)前瀏覽器是否支持WebSocket
if ('WebSocket' in window) {
//初始化連接webSocket
createWebSocket(wsUrl);
}
else {
alert('當(dāng)前瀏覽器 Not support websocket')
}
//將消息顯示在網(wǎng)頁上
function setMessageInnerHTML(innerHTML) {
console.log(innerHTML);
var data = JSON.parse(innerHTML);
console.log("-------------- websocket -----------------------------------");
}
//關(guān)閉WebSocket連接
function closeWebSocket() {
websocket.close();
}
//發(fā)送消息
function send(message) {
websocket.send(message);
}
· JAVA-后端代碼.
package com.ay.websocket;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint("/websocket/{userno}")
public class WebSocket {
//靜態(tài)變量,用來記錄當(dāng)前在線連接數(shù)邓梅。應(yīng)該把它設(shè)計(jì)成線程安全的。
private static int onlineCount = 0;
//concurrent包的線程安全Set邑滨,用來存放每個(gè)客戶端對(duì)應(yīng)的MyWebSocket對(duì)象日缨。若要實(shí)現(xiàn)服務(wù)端與單一客戶端通信的話,可以使用Map來存放掖看,其中Key可以為用戶標(biāo)識(shí)
private static ConcurrentHashMap<String, WebSocket> webSocketSet = new ConcurrentHashMap<String, WebSocket>();
//與某個(gè)客戶端的連接會(huì)話匣距,需要通過它來給客戶端發(fā)送數(shù)據(jù)
private Session session;
//當(dāng)前發(fā)消息的人員編號(hào)
private String userno = "";
/**
* 連接建立成功調(diào)用的方法
*
* @param session 可選的參數(shù)面哥。session為與某個(gè)客戶端的連接會(huì)話,需要通過它來給客戶端發(fā)送數(shù)據(jù)
*/
@OnOpen
public void onOpen(@PathParam(value = "userno") String param, Session session, EndpointConfig config) {
System.out.println(param);
userno = param;//接收到發(fā)送消息的人員編號(hào)
this.session = session;
webSocketSet.put(param, this);//加入map中
addOnlineCount(); //在線數(shù)加1
System.out.println("有新連接加入毅待!當(dāng)前在線人數(shù)為" + getOnlineCount());
}
/**
* 連接關(guān)閉調(diào)用的方法
*/
@OnClose
public void onClose() {
if (!userno.equals("")) {
webSocketSet.remove(userno); //從set中刪除
subOnlineCount(); //在線數(shù)減1
System.out.println("有一連接關(guān)閉尚卫!當(dāng)前在線人數(shù)為" + getOnlineCount());
}
}
/**
* 收到客戶端消息后調(diào)用的方法
*
* @param message 客戶端發(fā)送過來的消息
* @param session 可選的參數(shù)
*/
@SuppressWarnings("unused")
// @OnMessage
public void onMessage(String message, Session session) {
System.out.println("來自客戶端的消息:" + message);
// session.get
//群發(fā)消息
if (1 < 2) {
sendAll(message);
} else {
//給指定的人發(fā)消息
sendToUser(message);
}
}
/**
* 給指定的人發(fā)送消息
* @param message
*/
@OnMessage
public void sendToUser(String message) {
String sendUserno = message.split("[|]")[1];
String sendMessage = message.split("[|]")[0];
String now = getNowTime();
try {
if (webSocketSet.get(sendUserno) != null) {
webSocketSet.get(sendUserno).sendMessage(now + "用戶" + userno + "發(fā)來消息:" + " <br/> " + sendMessage);
} else {
System.out.println("當(dāng)前用戶不在線");
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 給所有人發(fā)消息
* @param message
*/
private void sendAll(String message) {
String now = getNowTime();
String sendMessage = message.split("[|]")[0];
//遍歷HashMap
for (String key : webSocketSet.keySet()) {
try {
//判斷接收用戶是否是當(dāng)前發(fā)消息的用戶
if (!userno.equals(key)) {
webSocketSet.get(key).sendMessage(now + "用戶" + userno + "發(fā)來消息:" + " <br/> " + sendMessage);
System.out.println("key = " + key);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 獲取當(dāng)前時(shí)間
*
* @return
*/
private String getNowTime() {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date);
return time;
}
/**
* 發(fā)生錯(cuò)誤時(shí)調(diào)用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("發(fā)生錯(cuò)誤");
error.printStackTrace();
}
/**
* 這個(gè)方法與上面幾個(gè)方法不一樣。沒有用注解尸红,是根據(jù)自己需要添加的方法吱涉。
*
* @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() {
WebSocket.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocket.onlineCount--;
}
public static void send2User(String sendUserno,String sendMessage){
try {
if (webSocketSet.get(sendUserno) != null) {
webSocketSet.get(sendUserno).sendMessage(sendMessage);
} else {
System.out.println("當(dāng)前用戶不在線");
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 給所有人發(fā)消息
* @param message
*/
public static void sendAlls(String message) {
String sendMessage = message.split("[|]")[0];
//遍歷HashMap
for (String key : webSocketSet.keySet()) {
try {
//判斷接收用戶是否是當(dāng)前發(fā)消息的用戶
webSocketSet.get(key).sendMessage(sendMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者