Vue页面限制跨浏览器只能打开一个标签页

Web前端 潘老师 9个月前 (07-20) 257 ℃ (0) 扫码查看

遇到个需求就是针对某个路由页面,只能打开一个tab标签页,不管是跨浏览器还是不跨浏览器,都进行限制,也就是说针对这一台设备的ip,只允许打开一个标签页,那么该怎么实现呢?

纯前端的方案肯定不行,没办法解决跨浏览器问题,只能寻求后端解决方案,这里的方案思路是:

该页面定时给后台发心跳,如果发现该页面已存在打开的情况,就保留最新打开的,关闭之前打开的,优点就是可以跨浏览器,缺点就是心跳频率较高,后端如果使用缓存多节点需要保证缓存一致性较麻烦,不用缓存就可能就要刷数据库

这里设定为单节点,直接使用缓存,缓存用的是hutool缓存,每个页面定时任务发送心跳都要携带打开或刷新页面的时间戳作为pageId进行区分,

前端代码实现

// data下面
heartbeatInterval: null,
pageId: (new Date()).getTime(),

// methods下面
startHeartbeat() {
   this.heartbeatInterval = setInterval(() => {
    this.sendHeartbeat();
 }, 2000);
},
stopHeartbeat() {
   clearInterval(this.heartbeatInterval);
},
sendHeartbeat() {
      send({"pageId":this.pageId})
        .then(response => {
          console.log (response.data);
          // 如果当前pageId时间戳值小于后台最新打开时记录的时间戳,则关闭当前
          if(this.pageId < response.data) {
            console.log("close")
            var currentView = this.$store.getters.visitedViews[0]
            for (currentView of this.$store.getters.visitedViews) {
              if (currentView.path === this.$route.path) {
                break
              }
            }
            // 关闭当前标签
            this.$store.dispatch("tagsView/delView", currentView)
            this.$router.push("/dashboard")
          }else {
            console.log("open")
          }
        })
        .catch(error => {
          // Handle errors if needed
        });
    },

//挂载执行
mounted() {
    this.startHeartbeat();
},

api的send方法:

export function send(data) {
  return request({
    url: '/sync/heartbeat',
    params: data,
    method: 'get'
  })
}

后端代码实现

private static final Cache<String, String> heartbeatCache = CacheUtil.newTimedCache(10 * 1000);
@GetMapping("/heartbeat")
    public ResponseResult handleHeartbeat(HttpServletRequest request) {
        String ipAddress = request.getRemoteAddr();
        String pageId = request.getParameter("pageId");

        String pageIdMax = heartbeatCache.get(ipAddress);
        if(pageIdMax == null) {
            heartbeatCache.put(ipAddress, pageId);
        }else if(Long.valueOf(pageId) > Long.valueOf(pageIdMax)){
            heartbeatCache.put(ipAddress, pageId);
        }
        return ResponseResult.success(heartbeatCache.get(ipAddress));
    }

主要就是根据ip进行缓存判断是否是最新打开的,如果是最新打开的直接替换pageId为最新打开的时间戳。

实验结果

同浏览器和跨浏览器都测试成功,左边为chrome,右边为edge,右边重复打开,左边自动关闭,延迟取决于你的心跳频率。

总结

这是一种比较容易想到的解决方案,如果你这样的页面还不止一个,那就继续优化下缓存的key,将其和页面名称挂钩即可,如果你有更好的方案,欢迎留言!


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/java/web/6845.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】