news 2026/5/1 3:46:20

Java 实现 Token 安全缓存:使用 ReentrantLock 和单例模式实现并发安全的 Token 管理器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 实现 Token 安全缓存:使用 ReentrantLock 和单例模式实现并发安全的 Token 管理器

在 Java 服务端开发中,Access Token 管理器必须是单例(Singleton),以确保整个应用只维护一个 Token 副本,并使用强大的可重入锁(ReentrantLock)来保证在高并发下的数据一致性。

1. Token 管理器结构:单例模式

我们使用最常用的懒汉式或饿汉式单例模式来创建AccessTokenManager类。这里以饿汉式为例,确保类加载时即完成初始化。

public class AccessTokenManager { // 状态变量 private String accessToken = null; private long expiresAt = 0L; // 精确到毫秒的过期时间戳 // 线程安全的核心:可重入锁 private final ReentrantLock lock = new ReentrantLock(); // 单例实例(饿汉式) private static final AccessTokenManager INSTANCE = new AccessTokenManager(); // 构造方法私有化 private AccessTokenManager() { // 初始化配置 } // 对外提供获取实例的静态方法 public static AccessTokenManager getInstance() { return INSTANCE; } // ... getAccessToken 方法实现 }

2. 核心方法:getAccessToken 的实现逻辑

getAccessToken方法负责检查当前 Token 的状态。其核心在于使用锁来保护 Token 刷新这一关键操作,同时允许大量并发的读操作在 Token 有效时无需等待锁。

逻辑流程:
  1. 快速检查:检查当前 Token 是否在安全阈值(例如 $10$ 分钟)内有效。如果有效,直接返回,避免锁竞争。

  2. 获取锁:如果 Token 即将过期或已过期,线程尝试获取ReentrantLock。此时,其他线程将被阻塞。

  3. 二次校验(Double Check):在获取锁后,必须再次检查 Token 状态。因为可能在线程 A 释放锁的瞬间,线程 B 立即获得了锁,但线程 A 已经完成了刷新。

  4. 执行刷新:如果二次校验仍显示 Token 无效,则线程 B 调用企业微信 API 执行刷新操作。

  5. 更新和释放:更新accessTokenexpiresAt,并在finally块中释放锁。

Java 代码关键部分:
private void refreshAccessToken() { // 实际调用企业微信 API 的代码 // 假设 API 返回 { "access_token": "new_token", "expires_in": 7200 } // 1. 调用 API 获取新 Token 和有效期 // APIResponse response = callWeComApi(); // 2. 更新状态 this.accessToken = "新获取的 Token"; // response.getAccessToken(); // 设定过期时间为当前时间 + 7200秒 - 600秒安全边际 this.expiresAt = System.currentTimeMillis() + (7200 - 600) * 1000L; } public String getAccessToken() { long currentTime = System.currentTimeMillis(); // 1. 快速检查 (无需锁) if (accessToken != null && currentTime < expiresAt) { return accessToken; } // 2. 尝试获取锁进行刷新 lock.lock(); try { // 3. 二次校验 (在锁保护下) if (accessToken != null && currentTime < expiresAt) { return accessToken; // 已被其他线程刷新,直接返回 } // 4. 执行刷新 refreshAccessToken(); return accessToken; } catch (Exception e) { // 记录日志或抛出异常 throw new RuntimeException("Access Token 刷新失败", e); } finally { // 5. 确保锁释放 lock.unlock(); } }

3. ReentrantLock 的优势

相比于使用synchronized关键字,ReentrantLock在这里的优势在于:

  • 明确的锁定和释放:必须手动调用lock()unlock(),强制要求开发者将释放锁的逻辑放置在finally块中,防止异常导致死锁。

  • 非阻塞尝试:ReentrantLock支持tryLock(),可以尝试获取锁,如果获取失败,线程可以选择做其他事情,而不是无限等待。

  • 条件变量:支持Condition,可以更精细地控制线程的等待和唤醒,虽然在这个简单的 Token 场景中用不到,但在更复杂的并发任务中非常有用。

通过这种设计,AccessTokenManager成为了一个高可用、线程安全的 Token 抽象层,为上层的所有 API 调用提供了稳定的保障。


QiWe开放平台提供了后台直登功能,登录成功后获取相关参数,快速Apifox在线测试,所有登录功能都是基于QiWe平台API自定义开发。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/26 11:37:40

Linux操作系统搭建和应用

Linux版本选择与安装 Linuxjies Linux是一个内核&#xff0c;最早由Linus发布现在的Linux&#xff0c;基本上是GUN/Linux很多Linux系统&#xff0c;例如Debian&#xff0c;都是基于Linux的衍生系统 版本介绍 ReHat 系列&#xff1a;Debian系列国产系列 获取和安装Linux 买云服务…

作者头像 李华
网站建设 2026/4/29 18:40:48

百度网盘下载提速终极方案:告别蜗牛速度的实战指南

你是否曾经经历过这样的煎熬时刻&#xff1a;面对百度网盘中急需的资料&#xff0c;下载速度却像蜗牛爬行&#xff0c;几十KB的速率让你几乎要抓狂&#xff1f;明明宽带速度足够&#xff0c;却只能在漫长的等待中消耗宝贵时间。今天&#xff0c;我将为你揭秘一个能够彻底解决这…

作者头像 李华
网站建设 2026/4/29 17:12:01

AI搜索排名GEO优化文旅业白皮书

AI搜索排名GEO优化文旅业白皮书引言随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;其在文旅业的应用日益广泛&#xff0c;尤其是在搜索引擎优化&#xff08;SEO&#xff09;领域。GEO优化作为一种新型的SEO策略&#xff0c;通过地理定位和个性化推荐&#…

作者头像 李华
网站建设 2026/4/17 0:01:57

【优化求解】基于遗传算法GA地面运动选择方法匹配广义条件强度测量的目标分布,目标IM的均值标准差CDF附含Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码获取及仿…

作者头像 李华
网站建设 2026/4/29 19:18:55

机械工程师关键技能详解

机械工程师作为制造业和工业领域的核心技术角色&#xff0c;其关键技能需兼顾理论深度、工程实践能力和跨学科协作能力。以下从核心技能模块展开&#xff0c;并结合实际场景说明其重要性及深入理解方向。一、基础理论&#xff1a;机械工程的底层逻辑机械工程的本质是“通过结构…

作者头像 李华
网站建设 2026/4/25 0:35:33

【MYSQL】IN查询优化

总结&#xff1a;在 MySQL 5.7 中&#xff0c;如果 WHERE 只作用于主表&#xff0c;但 JOIN 和 ORDER BY 很重&#xff0c; 就应当显式地缩小驱动表&#xff1b; 在 MySQL 8.0 中&#xff0c;优化器可能自动完成&#xff0c;但不能盲目信任。问题描述&#xff1a; //优化前 sel…

作者头像 李华