js监听浏览器关闭事件(区分刷新和关闭,兼容IE9,10,11,Edge,Chrome和Firefox)

2022-02-25发布 3646阅读
JavaScript
Java

由于各浏览器兼容性不同,所以首先要先区分各浏览器

var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串  
var isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器  
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判断是否IE浏览器
var isIE11 = userAgent.indexOf("rv:11.0") > -1; //判断是否是IE11浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器

1.chrome和FireFox 

if(!isIE && !isEdge && !isIE11) {//兼容chrome和firefox
	var _beforeUnload_time = 0, _gap_time = 0;
	var is_fireFox = navigator.userAgent.indexOf("Firefox")>-1;//是否是火狐浏览器
	window.onunload = function (){
		_gap_time = new Date().getTime() - _beforeUnload_time;
		if(_gap_time <= 5){
			$.post(&#039;webLoginController.do?delSession2&#039;);//浏览器关闭
		}else{//浏览器刷新
		}
 	}
	window.onbeforeunload = function (){ 
		_beforeUnload_time = new Date().getTime();
		if(is_fireFox){//火狐关闭执行
			$.post(&#039;webLoginController.do?delSession2&#039;);//浏览器关闭
		} 
	};
}

2.IE9, 10,11,Edge
这四个浏览器可以用beforeUnload事件监听浏览器关闭,但是无法区分刷新和关闭。所以我是用如下方法解决的:
思路:
IE9和10
这两个浏览器在刷新时先触发beforeunload事件,再触发unload事件。而在关闭时只触发beforeunload事件。所以根据这个特点。在beforeunload时调用A方法,将"1"存入session的"flagiii"属性中,并单开一个线程延迟一段时间执行B,在unload时再调用C将"flagiii"属性的值改为0;这样,在A中延迟一段时间后判断session中的flagiii属性的值是否为1,为1的话则是关闭,调用B方法(来操作你要操作的事情(我要做的是删除库中的内容和session))。为0是刷新,不调用B方法。
js:

if(isIE) {//兼容ie8,9,10
	window.onbeforeunload = function() {
		//alert(0);
		flagiii = "1";
		$.ajax({
			type: "post",
			url: "webLoginController.do?A",
			data:{"flagiii": flagiii},
			success: function() {
 
			},
			async:false
		});
				
	}
	window.onunload = onclose;
	function onclose(){
		flagiii = "0";
		$.ajax({
			type: "post",
			url: "webLoginController.do?storageData",
			data:{"flagiii": flagiii},
			success: function() {
					
			}
		});
	}
}

java:

/**
	 * 关闭浏览器时清除session兼容IE9和IE10浏览器
	 * 让方法延迟10s执行
	 * create by lucy
	 * 2017-12-19
	 */
	@RequestMapping(params = "A")
	public void A(
			@RequestParam("flagiii") String flagiii, 
			final HttpSession session, 
			final HttpServletRequest req
			) {
		session.setAttribute("flagiii", flagiii);
		Thread thread = new Thread(new Runnable(){
			@Override
			public void run() {
				System.out.println("begin");
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("end");
				delData(session, req);
			}			
		});
		thread.start();	
	}
	public void B(HttpSession session,HttpServletRequest req) {
		String flagiii = (String) session.getAttribute("flagiii");
		if("1".equals(flagiii)) {
			boolean isTrue = false;
			String userId = session.getAttribute("userId").toString();
			isTrue = webLoginService.deleteOnline(userId);
			//将安全日志插入数据库   map
			SafeLogInsertDBUtils.safeLogInsertDB(req, session, "关闭浏览器", true,StringUtil.LOGINOUT);
		}
	}
	/**
	 * 存储标记(配合delSessionData方法)
	 * @param flagiii
	 * create by lucy
	 * 2017-12-19
	 */
	@RequestMapping(params = "B")
	public void B(
		HttpSession session,
		@RequestParam("flagiii") String flagiii
		) {
		session.setAttribute("flagiii", flagiii); 
	}

IE11和Edge
思路类似于9和10,IE11和Edge浏览器在关闭时先触发beforeunload,然后再触发unload事件。而刷新时先触发beforeunload事件,再触发unload事件,再触发load事件。所以先在页面load后将"0"存入session,在beforeunload中存入"1"在unload事件中调用方法,开启一个新线程,延迟10s执行你想做的事。
js:

var flagiii = "0";
function onloadFun() {
	$.ajax({
 		type: "post",
 		url: "webLoginController.do?storageData",
 		data:{"flagiii": flagiii},
 		success: function() {
					
 		}
 	});
}
	    
if(isIE || isIE11 || isEdge) {
	//页面加载进来后将flagii存入session 
	onloadFun();
}	
	
if(isIE11 || isEdge) {//兼容ie11 edge
	window.onbeforeunload = function() {
		flagiii = "1";
		$.ajax({
			type: "post",
			url: "webLoginController.do?storageData",
			data:{"flagiii": flagiii},
			success: function() {
						
			},
			async:false
		});
	}
	window.onunload = onclose;
	function onclose(){
		$.ajax({
			type: "post",
			url: "webLoginController.do?delSessionData",
			data: {"rnd": Math.random()},
			success: function() {
						
			}
		});
	}
}

java: 

/**
	 * 存储标记(配合delSessionData方法)
	 * @param flagiii
	 * create by lucy
	 * 2017-12-19
	 */
	@RequestMapping(params = "storageData")
	@ResponseBody
	public void storageData(
			HttpSession session,
			@RequestParam("flagiii") String flagiii) {
		session.setAttribute("flagiii", flagiii);
	}
	/**
	 * 关闭浏览器时清除session兼容IE11和Edge浏览器
	 * 让方法延迟30s执行
	 * create by lucy
	 * 2017-12-19
	 */
	@RequestMapping(params = "delSessionData")
	@ResponseBody
	public void delSessionData(final HttpSession session, final HttpServletRequest req) {	
		Thread thread = new Thread(new Runnable(){
			@Override
			public void run() {
				System.out.println("begin");
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("end");
				delData(session, req);
			}			
		});
		thread.start();	
	}

注意: 在beforeunload事件中的ajax请求使用同步(async: false),否则无法发送。