【实用工具类】基于 Guava Cache 实现通用 Token 缓存工具类(附完整源码)

【实用工具类】基于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官方指南

相关推荐
To Be Clean Coder2 小时前
【Spring源码】getBean源码实战(二)
java·后端·spring
Ahtacca4 小时前
Redis 五大常用数据类型详解及 Java 客户端(RedisTemplate)操作实战
java·数据库·redis·学习·缓存
0和1的舞者4 小时前
SpringAOP详解(二)
学习·spring·切面·代理·知识·springaop
廋到被风吹走4 小时前
【Spring】Spring Cache 深度解析
java·后端·spring
七夜zippoe5 小时前
响应式编程基石 Project Reactor源码解读
java·spring·flux·响应式编程·mono·订阅机制
IT 行者5 小时前
Spring Framework 6.x 异常国际化完全指南:让错误信息“说“多国语言
java·后端·spring·异常处理·problemdetail·国际化i18n
鱼跃鹰飞6 小时前
面试题:Spring事务失效的八大场景
数据库·mysql·spring
C_心欲无痕6 小时前
nodejs - pnpm解决幽灵依赖
前端·缓存·npm·node.js
wa的一声哭了6 小时前
内积空间 内积空间二
java·开发语言·python·spring·java-ee·django·maven
cike_y6 小时前
Spring使用注解开发
java·后端·spring·jdk1.8