本地缓存Caffeine

Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x)spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件

一、引入依赖

 <dependency>
     <groupId>com.github.ben-manes.caffeine</groupId>
     <artifactId>caffeine</artifactId>
     <version>2.8.8</version>
 </dependency>
  • caffeine3.x版本不支持jdk1.8,所以这里选用2.8.8

二、自定义缓存空间枚举

一个项目里可能需要缓存的数据有很多,比如用户信息,权限信息,菜单信息等等,我们需要给不同的场景分配不同的命名空间,并设置不同的过期时间

public enum CacheEnum {
    /**
     * 用户缓存,缓存时间单位/秒
     */
    CACHE_USERS("users", 2),
    /**
     * 菜单缓存,缓存时间单位/秒
     */
    CACHE_MENU("menu", 2),
    ;
    /**
     * 缓存名称
     */
    private final String name;
    /**
     * 过期时间
     */
    private final int expires;
	...
}

三、缓存配置类CacheConfig

@Slf4j
public class CacheConfig {
   
    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<CaffeineCache> list = new ArrayList<>();
        //循环添加枚举类中自定义的缓存
        for (CacheEnum cacheEnum : CacheEnum.values()) {
            list.add(new CaffeineCache(cacheEnum.getName(),
                    Caffeine.newBuilder()
                            .initialCapacity(50)
                            .maximumSize(1000)
                             // 设置过期时间
                            .expireAfterWrite(cacheEnum.getExpires(), TimeUnit.SECONDS)
                            .build()));
        }
        cacheManager.setCaches(list);
        log.info("[cacheManager加载完成]");
        return cacheManager;
    }
}
  • initialCapacity=[integer]: 初始的缓存空间大小
  • maximumSize=[long]: 缓存的最大条数
  • maximumWeight=[long]: 缓存的最大权重
  • expireAfterAccess=[duration]: 最后一次写入或访问后经过固定时间过期
  • expireAfterWrite=[duration]: 最后一次写入后经过固定时间过期
  • refreshAfterWrite=[duration]: 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存
  • weakKeys: 打开key的弱引用
  • weakValues:打开value的弱引用
  • softValues:打开value的软引用
  • recordStats:开发统计功能

注意:

  • expireAfterWriteexpireAfterAccess同事存在时,以expireAfterWrite为准。
  • maximumSizemaximumWeight不可以同时使用
  • weakValuessoftValues不可以同时使用

如果是在自定义的starter里,还需要在MATE-INFO/spring.factories中配置EnableAutoConfiguration

四、CacheUtils工具类

public enum CacheUtil {
    
    X;
    
    private final CacheManager cm;

    CacheUtil() {
        cm = SpringUtil.getBean("cacheManager", CacheManager.class);
    }

    /**
     * 添加缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @param value     缓存值
     */
    public void put(String cacheName, String key, Object value) {
        Cache cache = cm.getCache(cacheName);
        cache.put(key, value);
    }

    /**
     * 获取缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @return
     */
    public <T> Optional<T> get(String cacheName, String key) {
        Cache cache = cm.getCache(cacheName);
        if (cache == null) {
           return Optional.empty();
        }
        Cache.ValueWrapper valueWrapper = cache.get(key);
        if (null == valueWrapper) {
            return Optional.empty();
        }
        return  Optional.of((T) valueWrapper.get());
    }

    /**
     * 失效缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     */
    public void evict(String cacheName, String key) {
        Cache cache = cm.getCache(cacheName);
        if (cache != null) {
            cache.evict(key);
        }
    }
}
  • 工具类需要保证都是单例的,而枚举类天然支持单例,X表示工具类
  • 获取缓存使用Optional作为返回,是为了提醒使用者可能返回null的情况,需要做针对处理

五、单元测试

    @Test
    public void test_cache_put() throws InterruptedException {
        CacheUtil.X.put(CacheEnum.CACHE_USERS.getName(), "users", "zhangsan");
        CacheUtil.X.put(CacheEnum.CACHE_MENU.getName(), "menus", Arrays.asList("1", "2", "3", "4"));

        Optional<String> users = CacheUtil.X.get(CacheEnum.CACHE_USERS.getName(), "users");
        if (users.isPresent()) {
            String str = users.get();
            System.out.println(str);
        }
        Optional<List<String>> menus = CacheUtil.X.get(CacheEnum.CACHE_MENU.getName(), "menus");
        menus.ifPresent(System.out::println);

        // 测试缓存过期情况
        Thread.sleep(2000);
        Optional<String> users2 = CacheUtil.X.get(CacheEnum.CACHE_USERS.getName(), "users");
        if (users2.isPresent()) {
            String str = users2.get();
            System.out.println(str);
        }
        Optional<List<String>> menus2 = CacheUtil.X.get(CacheEnum.CACHE_MENU.getName(), "menus");
        menus2.ifPresent(System.out::println);
    }

我是一零贰肆,一个关注Java技术和记录生活的博主。

欢迎扫码关注“一零贰肆的公众号”,一起学习,共同进步,多看路,少踩坑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值