使用websocket來監控是否異常退出或異常關閉登陸窗口
知識點: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來監控是否異常退出或異常關閉登陸窗口