1. 程式人生 > >使用websocket來監控是否異常退出或異常關閉登陸窗口

使用websocket來監控是否異常退出或異常關閉登陸窗口

ppi gets println except ajax 機制 方法 當前在線 string

知識點websocket獲取本機IP&websocket前後端消息推送

解決的實際問題

前端用戶登陸時同一個賬號密碼只允許在一個IP上登陸;

同一個IP只允許登陸一個賬戶密碼。

主要實現思路:

1.前端websocket 推送消息,創建一個new websocket,將前端的部分參數傳給後臺

sendMsg() //發送數據

2.前後端建立連接觸發,客戶端可以通過這個URL來連接到WebSocket服務器端,當連接成功時則調用其自身的onOpen方法

後端增加session參數,通過它來給客戶端發送數據。

3.當出現異常或者錯誤時候前後端都有對應的錯誤異常處理機制

後端onError()處理:error.printStackTrace();

前端onerror處理:websocket.close();

4.監聽窗口關閉事件

當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。

window.onbeforeunload = function () {
  websocket.close();
}

相關代碼實現

前端js

// websocket 推送消息

localIP通過調用接口查詢,後面給出,這個是本機IP
sendWebSocketMsg();

function sendWebSocketMsg(){
//判斷當前瀏覽器是否支持WebSocket
// var test = window.location.host;
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(userName);
}, 10000);
*/
}
//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。
window.onbeforeunload = function () {
websocket.close();
}
//接收到消息的回調方法
websocket.onmessage = function (event) {
}

//連接關閉的回調方法
websocket.onclose = function () {
websocket.close();
}
}

java實現

@ServerEndpoint("/websocket/{tstr}")
public class WebSocketForJSP {
//靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。
private static int onlineCount = 0;

//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;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在線數加1
System.out.println("有新連接加入!當前在線人數為" + getOnlineCount());
}
// public void onOpen(@PathParam("name") String name, Session session){
// this.userName = name;
// this.session = session;
// webSocketSet.add(this); //加入set中
// addOnlineCount(); //在線數加1
// System.out.println("有新連接加入!當前在線人數為" + getOnlineCount());
// }

/**
* 連接關閉調用的方法
*/
@OnClose
public void onClose(){
webSocketSet.remove(this); //從set中刪除
subOnlineCount(); //在線數減1
System.out.println("有一連接關閉!當前在線人數為" + getOnlineCount());
}

/**
* 收到客戶端消息後調用的方法
* @param message 客戶端發送過來的消息
* @param session 可選的參數
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("來自客戶端的消息:" + message);
/*
userName = message;
for(WebSocketForJSP item: webSocketSet){
try {
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() {
WebSocketForJSP.onlineCount++;
}

public static synchronized void subOnlineCount() {
WebSocketForJSP.onlineCount--;
}
}

支持javax的包需要引入

.xml

<dependency>
  <groupId>javax</groupId>
  <artifactId>javaee-api</artifactId>
  <version>7.0</version>
  <scope>provided</scope>
</dependency>

有關獲取本機IP

需要調用某個接口,將request帶過去 調用下面的方法即可實現,這個接口隨便自己些,只要能ajax調用到就可以

@RequestMapping(value="getip")
@ResponseBody
public String getip(HttpServletRequest request){
User userInfo = (User) request.getSession().getAttribute("user");
String ip = userInfo.getIpaddr();
return ip;
}

使用websocket來監控是否異常退出或異常關閉登陸窗口