软件教程 2025年08月6日
0 收藏 0 点赞 875 浏览 1895 个字
摘要 :

文章目录 前端代码实现 后端代码实现 实验结果 总结 遇到个需求就是针对某个路由页面,只能打开一个tab标签页,不管是跨浏览器还是不跨浏览器,都进行限制,也就是说针……




  • 前端代码实现
  • 后端代码实现
  • 实验结果
  • 总结

遇到个需求就是针对某个路由页面只能打开一个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,右边重复打开,左边自动关闭,延迟取决于你的心跳频率。
Vue页面限制跨浏览器只能打开一个标签页

总结

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

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6230.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号