一个浏览器只运行登录一个用户

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_30682027/article/details/83004059


参考:

刷新页面的方法

使用beforeSend提升用户体验

1. 需求

在每个浏览器中,如果用户已经登录了系统,那么用户打开新的页面,默认是之前已经登录的用户,不再重新显示登录页面。

2. 解决方案

有两种方案,但是服务端需要做改动。

2.1. 服务端

对要跳转到登录页面的请求进行拦截,检测其中是否有已登录标识。如果有,且没有超时,则直接重定向到登录之后的页面;否则,跳转到登录页面

/**
 * 这里只是模拟一下,提供一个思路,具体实现还要自己动手
 */
@RequestMapping(value = "/login")
public ModelAndView loginView(HttpServletRequest request) {
    ModelAndView mav = new ModelAndView();
    //这里假设登录信息保存在cookie
    //然后从cookie中取出
    String token="";
    if(token != null && !token.equals("")){
        //todo:判断超时
        if(不超时){
            mav.setViewName(登录后页面);
        }else{
             mav.setViewName(登录页面);
        }
    }else{
        mav.setViewName(登录页面);
    }
    return mav;
}

2.2. 前端

前端要考虑的情况要多一些。因为项目中所有的请求都是通过jquery的ajax请求,所以这里选择对jquery的ajax进行增强处理

这种写法有点类似于代理模式。

//扩展Jquery
(function($){
    // 扩展ajax方法,用来统一处理后端抛出的异常
    //备份jquery的ajax方法
    var _ajax=$.ajax;
    //重写jquery的ajax方法
    $.ajax=function(opt){
        //备份opt中error和success方法
        var fn = {
            error:function(XMLHttpRequest, textStatus, errorThrown){},
            success:function(data, textStatus){},
            complete:function(XMLHttpRequest, textStatus){},
            beforeSend : function(XMLHttpRequest){}
        };
        if(opt.error){
            fn.error=opt.error;
        }
        if(opt.success){
            fn.success=opt.success;
        }
        if(opt.beforeSend){
            fn.beforeSend=opt.beforeSend;
        }
        if(opt.complete){
            fn.complete=opt.complete;
        }
        // //扩展增强处理
        var _opt = $.extend(opt, {
            error: function (xhr,textStatus,errorThrown) {
                //TODO:ajax发生错误时的统一处理
                if(fn.error && typeof fn.error === 'function') {
                    fn.error(xhr, textStatus, errorThrown);
                }
            },
            success: function (data, textStatus) {
                //TODO:ajax成功是的统一处理
                fn.success(data, textStatus);
            },
            beforeSend: function (XHR,obj) {
                fn.beforeSend(XHR,obj);
            },
            complete: function (XHR, TS) {
                //请求完成后回调函数 (请求成功或失败之后均调用)。
                fn.complete(XHR, TS);
            }
        });
        return _ajax(_opt);
    };
})(jQuery);

因为在登录账号A后,用户有可能重新打开一个新的页面,然后注销并登录一个新的账号B。这时用户在A页面的操作就可能引发数据不一致问题。

所以,要对这种情况进行处理。处理方法有两种:

2.2.1. 强制刷新页面

$(function () {
    (function ($) {
        var _ajax = $.ajax;
        // 扩展ajax方法,用来处理登录后的双页面问题
        $.ajax = function (opt) {
            var fn = {
                beforeSend: function () {
                }
            };
            if (opt.beforeSend) {
                fn.beforeSend = opt.beforeSend;
            }
            //如果登录状态不一致,刷新当前页面。
            // 解决两个页面同时点开,在第二个页面重新登录但是在第一个页面操作的问题
            return _ajax($.extend(opt, {
                beforeSend: function (XHR, obj) {
                    if (cookie中的用户信息 !== 内存变量中的用户信息) {
                        alert('提示信息');
                        //参数为true表示忽略缓存强制刷新;为false表示会首先检查是否修改过,如果被修改则重新加载,否则不加载
                        location.reload(true);
                        //终止请求
                        XHR.abort();
                    }
                    fn.beforeSend(XHR, obj);
                }
            }));
        };
    })(jQuery);
});

2.2.2. 关闭之前的页面

这种写法的灵感来自于CSDN。之前CSDN在使用Markdown对同一篇博客进行编辑时,如果打开了第二个编辑页,那么就会自动关闭第一个编辑页。

但是,并没有想到实现的方法。遗憾

个人觉得CSDN的实现原理如:
首先,我们看一下JavaScript新建标签页和关闭标签页的方法。这里以打开百度为例
第一、打开百度首页(简称A页面),在控制台执行如下代码

//window.open的返回值就是window.opener,也就是打开页面的对象
var opener = window.open('https://www.baidu.com/', "_blank");

这时,将打开一个新的百度标签页(简称B页面)

第二、在A页面的控制台查看window.opener其结果为null;在B页面查看,结果是一个window对象

第三、在A页面执行window.close(),报错:Scripts may close only the windows that were opened by it.;在B页面执行,成功关闭标签页

第四、在A页面执行opener.close(),B页面被关闭

综上,记录opener,检测到有新值添加就先关闭原先的页面,然后打开新的页面;或者将页面的打开者作为参数传递给其它页面,由其它页面关闭。

3. window API

window-MDN

3.1. window.open

参考:window.open-MDN

3.1.1. window.location.reload

用来刷新当前页面。该方法只有一个参数,当值为 true 时,将强制浏览器从服务器加载页面资源,当值为 false 或者未传参时,浏览器则可能从缓存中读取页面。

该方法在跨域调用(执行该方法的脚本文件的域和 Location 对象所在页面的跨不同)时,将会抛出 DOMException 异常。

语法:

object.reload(forcedReload);

forcedReload 可选

该参数要求为 布尔 类型,当取值为 true 时,将强制浏览器从服务器重新获取当前页面资源,而不是从浏览器的缓存中读取,如果取值为 false 或不传该参数时,浏览器则可能会从缓存中读取当前页面。

示例

// 无缓存刷新页面(但页面引用的资源还是可能使用缓存,
// 大多数浏览器可以通过设置在打开开发者工具时禁用缓存实现无缓存需求)
document.location.reload(true);

猜你喜欢

转载自blog.csdn.net/qq_30682027/article/details/83004059