【实用工具类】基于Guava Cache实现通用Token缓存工具类(附完整源码)
在日常开发中,Token缓存是非常常见的场景------比如接口调用的访问令牌、用户登录态Token、第三方服务的临时凭证等。如果每次使用Token都重新生成/请求,会增加系统开销;而手写缓存又容易出现重复造轮子、边界处理不完整的问题。
今天给大家分享一个基于Guava Cache实现的通用Token缓存工具类,支持泛型、自定义配置、自动刷新、失效监听等核心能力,开箱即用,适配绝大多数Token缓存场景。
一、核心特性
这个TokenCache工具类具备以下核心优势:
- ✅ 泛型支持:适配任意类型的Token(String、自定义对象、整数等),无需重复编写缓存逻辑;
- ✅ 灵活配置:支持自定义缓存最大容量、过期时间、并发级别,满足不同场景需求;
- ✅ 自动刷新:获取Token时若不存在/已过期,自动触发刷新逻辑,无需手动判断;
- ✅ 失效监听:缓存失效时可监听并打印原因,便于问题排查;
- ✅ 便捷操作:封装了存、取、失效、清空、统计等常用方法,调用简单。
二、完整源码
先贴出完整的工具类源码,建议直接收藏备用:
java
package com.dolphin.util;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* 支持泛型的Token缓存类,基于Guava Cache实现
* 提供Token的存储、获取、自动刷新和失效等功能
*/
public class TokenCache<T> {
// 基于LRU淘汰策略的核心缓存对象
private final Cache<String, T> tokenCache;
// 默认构造函数:最大容量1000,写入后30分钟过期,并发级别16
public TokenCache() {
this(1000, 1800, TimeUnit.SECONDS, 16);
}
/**
* 自定义配置的构造函数
*
* @param maxSize 最大缓存数量(LRU淘汰阈值)
* @param expireSeconds 过期时间(写入后多久过期)
* @param timeUnit 时间单位
* @param concurrencyLevel 并发级别(同时写缓存的线程数)
*/
public TokenCache(int maxSize, int expireSeconds, TimeUnit timeUnit, int concurrencyLevel) {
this.tokenCache = CacheBuilder.newBuilder()
// LRU核心:缓存达到最大容量时,淘汰最少使用的缓存
.maximumSize(maxSize)
// 写入后过期(区别于访问后过期),适合Token这类有固定有效期的场景
.expireAfterWrite(expireSeconds, timeUnit)
// 并发级别:控制缓存分段数,提升多线程读写性能
.concurrencyLevel(concurrencyLevel)
// 失效监听器:打印失效的Key和原因,便于排查问题
.removalListener((RemovalListener<String, T>) notification ->
System.out.println("Token失效:" + notification.getKey() + ",原因:" + notification.getCause()))
.build();
}
/**
* 存入/更新Token(覆盖式)
* @param key 缓存Key(建议按业务规则命名,如user_1_token、api_access_token)
* @param token 缓存的Token对象
*/
public void putToken(String key, T token) {
tokenCache.put(key, token);
}
/**
* 普通获取Token(不存在/已过期返回null)
* @param key 缓存Key
* @return 缓存的Token,无则返回null
*/
public T getToken(String key) {
return tokenCache.getIfPresent(key);
}
/**
* 带自动刷新的Token获取
* 若Key不存在/已过期,自动执行refreshLogic生成新Token并缓存
* @param key 缓存Key
* @param refreshLogic Token刷新逻辑(Callable接口,支持抛出异常)
* @return 最新的Token
*/
public T getTokenWithRefresh(String key, Callable<T> refreshLogic) {
try {
return tokenCache.get(key, refreshLogic);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
// 解包RuntimeException,避免外层捕获冗余异常
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
}
throw new RuntimeException("Token刷新失败", cause);
}
}
/**
* 强制失效指定Token
* @param key 缓存Key
*/
public void invalidateToken(String key) {
tokenCache.invalidate(key);
}
/**
* 获取当前缓存大小
* @return 缓存中的有效Key数量
*/
public long size() {
return tokenCache.size();
}
/**
* 清空所有缓存
*/
public void invalidateAll() {
tokenCache.invalidateAll();
}
}
三、核心代码解析
1. 依赖说明
该工具类基于Guava Cache实现,需先引入Guava依赖(Maven示例):
xml
<!-- Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version> <!-- 建议使用最新稳定版 -->
</dependency>
2. 关键设计解析
- LRU淘汰策略 :通过
maximumSize设置最大容量,当缓存达到阈值时,自动淘汰最少使用的Token,避免内存溢出; - 过期策略 :使用
expireAfterWrite(写入后过期),适合Token这类"生成后有固定有效期"的场景(若需"访问后过期",可替换为expireAfterAccess); - 泛型设计 :类定义
TokenCache<T>,使得缓存可以存储任意类型的Token(字符串、自定义Token对象、整数等); - 自动刷新 :
getTokenWithRefresh方法结合Callable,实现"懒加载+自动刷新",无需手动判断Token是否有效; - 失效监听 :
removalListener监听缓存失效事件,可扩展为记录日志、发送告警、清理关联数据等。
四、使用示例
下面通过完整示例演示工具类的核心用法:
java
public class TokenCacheExample {
public static void main(String[] args) {
// 1. 创建默认配置的字符串类型Token缓存
TokenCache<String> stringCache = new TokenCache<>();
// 2. 存储Token
stringCache.putToken("user1_token", "abc123456");
// 3. 普通获取Token
String token = stringCache.getToken("user1_token");
System.out.println("普通获取Token: " + token); // 输出:abc123456
// 4. 带自动刷新的获取(Token不存在则执行刷新逻辑)
String newToken = stringCache.getTokenWithRefresh("user2_token", () -> {
// 此处可替换为实际的Token生成逻辑(如调用接口获取新Token)
return "new_token_" + System.currentTimeMillis();
});
System.out.println("自动刷新后获取Token: " + newToken); // 输出:new_token_17xxxxxxxxx
// 5. 强制失效Token
stringCache.invalidateToken("user1_token");
System.out.println("失效后获取Token: " + stringCache.getToken("user1_token")); // 输出:null
// 6. 自定义配置的缓存(存储Integer类型,最大容量500,1小时过期,并发级别8)
TokenCache<Integer> intCache = new TokenCache<>(500, 3600, TimeUnit.SECONDS, 8);
intCache.putToken("counter", 100);
System.out.println("整数类型Token: " + intCache.getToken("counter")); // 输出:100
// 7. 获取缓存大小
System.out.println("缓存大小: " + intCache.size()); // 输出:1
// 8. 清空所有缓存
intCache.invalidateAll();
System.out.println("清空后缓存大小: " + intCache.size()); // 输出:0
}
}
五、注意事项与扩展建议
1. 适用场景
该工具类基于本地缓存(Guava Cache),适合单机/低并发场景的Token缓存;若为分布式系统,建议结合Redis实现分布式缓存(可基于该工具类扩展Redis适配层)。
2. 配置优化
maximumSize:根据业务场景设置,避免过大导致内存占用过高,过小导致频繁淘汰;expireAfterWrite:建议与Token的实际有效期匹配(如第三方Token有效期1小时,缓存过期时间可设为55分钟,预留刷新时间);concurrencyLevel:默认16,多核CPU场景可适当调大(如32),但不宜过大(会增加分段开销)。
3. 扩展方向
- 失效监听增强:将
System.out.println替换为日志框架(如SLF4J),记录失效详情; - 异常处理扩展:针对
getTokenWithRefresh的刷新逻辑,增加重试机制; - 缓存统计:开启Guava Cache的统计功能(
recordStats()),监控缓存命中率、失效次数等; - 自定义过期策略:结合业务实现更复杂的过期规则(如不同Key设置不同过期时间)。
六、总结
这个TokenCache工具类封装了Guava Cache的核心能力,通过泛型和便捷的API设计,解决了Token缓存的通用场景需求。代码简洁、易扩展,可直接集成到项目中,减少重复开发成本。
如果你的项目中有Token缓存的需求,不妨试试这个工具类,也欢迎在评论区交流优化建议~
💡 本文源码已亲测可运行,如需更多Guava Cache高级用法,可参考官方文档:Guava Cache官方指南