懶得寫了,這裏有介紹:https://my.oschina.net/kdy1994/blog/809802java
最新的一個項目中由於要控制用戶只能在一個地方登錄,及時顯示登陸狀況信息,就是用的WebSocket實現的web
服務端實現json
@EnableWebSocket 聲明該類支持WebSocket瀏覽器
/** * @ServerEndpoint 註解是一個類層次的註解,它的功能主要是將目前的類定義成一個websocket服務器端, * 註解的值將被用於監聽用戶鏈接的終端訪問URL地址,客戶端能夠經過這個URL來鏈接到WebSocket服務器端 */ @ServerEndpoint("/websocket/{tstr}") public class WebSocketForJSP { //concurrent包的線程安全Set,用來存放每一個客戶端對應的MyWebSocket對象。若要實現服務端與單一客戶端通訊的話,可使用Map來存放,其中Key能夠爲用戶標識 public static CopyOnWriteArraySet<WebSocketForJSP> webSocketSet = new CopyOnWriteArraySet<WebSocketForJSP>(); //與某個客戶端的鏈接會話,須要經過它來給客戶端發送數據 private Session session; // 登陸用戶名 public String userName; //所屬IP public String ip; /** * 鏈接創建成功調用的方法 * @param session 可選的參數。session爲與某個客戶端的鏈接會話,須要經過它來給客戶端發送數據 */ @OnOpen public void onOpen(@PathParam("tstr") String tstr, Session session){ String[] str = tstr.split(","); this.userName = str[0]; this.ip = str[1]; this.session = session; Boolean isIn = false; for (WebSocketForJSP socket : WebSocketForJSP.webSocketSet) { if(userName.equals(socket.userName) && ip.equals(socket.ip)){ isIn = true; System.out.println("websocket已經鏈接:"+userName+" "+ip); //刪除老的,新增新的 webSocketSet.remove(socket); webSocketSet.add(this); break; } } if(! isIn){ webSocketSet.add(this); //加入set中 System.out.println("有新鏈接加入!當前在線人數爲" + getOnlineCount()); } } /** * 鏈接關閉調用的方法 */ @OnClose public void onClose(){ webSocketSet.remove(this); //從set中刪除 System.out.println("有一鏈接關閉!當前在線人數爲" + getOnlineCount()); } /** * 收到客戶端消息後調用的方法 * @param message 客戶端發送過來的消息 * @param session 可選的參數 */ @OnMessage public void onMessage(String message, Session session) { System.out.println("來自客戶端的消息:" + message); /* try { this.sendMessage("服務器回覆消息:"+this.userName); } catch (IOException e) { e.printStackTrace(); } */ } /** * 發生錯誤時調用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ System.out.println("發生錯誤"); this.onClose(); error.printStackTrace(); } /** * 這個方法與上面幾個方法不同。沒有用註解,是根據本身須要添加的方法。 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ System.out.println("返回結果----------------->:"+message); this.session.getAsyncRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return WebSocketForJSP.webSocketSet.size(); } }
//而後在用戶登陸的地方判斷便可安全
// 判斷是否已經登陸 for(WebSocketForJSP item: WebSocketForJSP.webSocketSet){ if(item.userName.equals(userName)){ return "用戶已在其餘電腦登陸!"; } String userIp = IpUtils.getIpAddr(request); if(item.ip.equals(userIp)){ return "同一段IP只容許登錄一個用戶"; } }
客戶端調用服務器
/** * 推送 用戶java獲取用戶信息 */ function sendWebSocketMsg(){ //判斷當前瀏覽器是否支持WebSocket // var test = window.location.host; // var IP = test.split(":"); var tstr = userName +","+localIP if ('WebSocket' in window) { //此處參數只容許字符串,不支持json websocket = new WebSocket(getRootPath().replace("http","ws")+"/websocket/"+tstr); } //鏈接發生錯誤的回調方法 websocket.onerror = function () { websocket.close(); }; //鏈接成功創建的回調方法 websocket.onopen = function () { //setInterval(function(){ websocket.send(tstr); //}, 10 * 1000); } //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket鏈接,防止鏈接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function () { websocket.close(); } //接收到消息的回調方法 websocket.onmessage = function (event) { try { var result = JSON.parse(event.data); // 是不是對象 if(typeof(result) == "object" && Object.prototype.toString.call(result).toLowerCase() == "[object object]" && !result.length){ if(result.msgType != null && typeof(result.msgType) != "undefined"){ // 負載-自動化運維 debugger; window.showScriptDiagle(result); }else{ debugger; // 回顯健康-運維經驗 $(window.frames[0])[0].doScriptFn(result); } } } catch (e) { if("logOut" == event.data){ websocket.close(); sessionStorage.setItem("oneUser",true); location.href = getRootPath()+"/jsps/login/login.jsp"; }else if("logOutByIp" == event.data){ websocket.close(); sessionStorage.setItem("oneIp",true); location.href = getRootPath()+"/jsps/login/login.jsp"; } } console.log(event.data); } //鏈接關閉的回調方法 websocket.onclose = function () { websocket.close(); } }