【实用工具类】基于Guava Cache实现通用Token缓存工具类(附完整源码)
在日常开发中,Token缓存是非常常见的场景——比如接口调用的访问令牌、用户登录态Token、第三方服务的临时凭证等。如果每次使用Token都重新生成/请求,会增加系统开销;而手写缓存又容易出现重复造轮子、边界处理不完整的问题。
今天给大家分享一个基于Guava Cache实现的通用Token缓存工具类,支持泛型、自定义配置、自动刷新、失效监听等核心能力,开箱即用,适配绝大多数Token缓存场景。
一、核心特性
这个TokenCache工具类具备以下核心优势:
- ✅泛型支持:适配任意类型的Token(String、自定义对象、整数等),无需重复编写缓存逻辑;
- ✅灵活配置:支持自定义缓存最大容量、过期时间、并发级别,满足不同场景需求;
- ✅自动刷新:获取Token时若不存在/已过期,自动触发刷新逻辑,无需手动判断;
- ✅失效监听:缓存失效时可监听并打印原因,便于问题排查;
- ✅便捷操作:封装了存、取、失效、清空、统计等常用方法,调用简单。
二、完整源码
先贴出完整的工具类源码,建议直接收藏备用:
packagecom.dolphin.util;importcom.google.common.cache.Cache;importcom.google.common.cache.CacheBuilder;importcom.google.common.cache.RemovalListener;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.TimeUnit;/** * 支持泛型的Token缓存类,基于Guava Cache实现 * 提供Token的存储、获取、自动刷新和失效等功能 */publicclassTokenCache<T>{// 基于LRU淘汰策略的核心缓存对象privatefinalCache<String,T>tokenCache;// 默认构造函数:最大容量1000,写入后30分钟过期,并发级别16publicTokenCache(){this(1000,1800,TimeUnit.SECONDS,16);}/** * 自定义配置的构造函数 * * @param maxSize 最大缓存数量(LRU淘汰阈值) * @param expireSeconds 过期时间(写入后多久过期) * @param timeUnit 时间单位 * @param concurrencyLevel 并发级别(同时写缓存的线程数) */publicTokenCache(intmaxSize,intexpireSeconds,TimeUnittimeUnit,intconcurrencyLevel){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对象 */publicvoidputToken(Stringkey,Ttoken){tokenCache.put(key,token);}/** * 普通获取Token(不存在/已过期返回null) * @param key 缓存Key * @return 缓存的Token,无则返回null */publicTgetToken(Stringkey){returntokenCache.getIfPresent(key);}/** * 带自动刷新的Token获取 * 若Key不存在/已过期,自动执行refreshLogic生成新Token并缓存 * @param key 缓存Key * @param refreshLogic Token刷新逻辑(Callable接口,支持抛出异常) * @return 最新的Token */publicTgetTokenWithRefresh(Stringkey,Callable<T>refreshLogic){try{returntokenCache.get(key,refreshLogic);}catch(ExecutionExceptione){Throwablecause=e.getCause();// 解包RuntimeException,避免外层捕获冗余异常if(causeinstanceofRuntimeException){throw(RuntimeException)cause;}thrownewRuntimeException("Token刷新失败",cause);}}/** * 强制失效指定Token * @param key 缓存Key */publicvoidinvalidateToken(Stringkey){tokenCache.invalidate(key);}/** * 获取当前缓存大小 * @return 缓存中的有效Key数量 */publiclongsize(){returntokenCache.size();}/** * 清空所有缓存 */publicvoidinvalidateAll(){tokenCache.invalidateAll();}}三、核心代码解析
1. 依赖说明
该工具类基于Guava Cache实现,需先引入Guava依赖(Maven示例):
<!-- 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监听缓存失效事件,可扩展为记录日志、发送告警、清理关联数据等。
四、使用示例
下面通过完整示例演示工具类的核心用法:
publicclassTokenCacheExample{publicstaticvoidmain(String[]args){// 1. 创建默认配置的字符串类型Token缓存TokenCache<String>stringCache=newTokenCache<>();// 2. 存储TokenstringCache.putToken("user1_token","abc123456");// 3. 普通获取TokenStringtoken=stringCache.getToken("user1_token");System.out.println("普通获取Token: "+token);// 输出:abc123456// 4. 带自动刷新的获取(Token不存在则执行刷新逻辑)StringnewToken=stringCache.getTokenWithRefresh("user2_token",()->{// 此处可替换为实际的Token生成逻辑(如调用接口获取新Token)return"new_token_"+System.currentTimeMillis();});System.out.println("自动刷新后获取Token: "+newToken);// 输出:new_token_17xxxxxxxxx// 5. 强制失效TokenstringCache.invalidateToken("user1_token");System.out.println("失效后获取Token: "+stringCache.getToken("user1_token"));// 输出:null// 6. 自定义配置的缓存(存储Integer类型,最大容量500,1小时过期,并发级别8)TokenCache<Integer>intCache=newTokenCache<>(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官方指南