当前位置: 首页 > 工具软件 > Caffeine > 使用案例 >

SpringBoot + Caffeine本地缓存

姚培
2023-12-01


SpringBoot + Caffeine配置

Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。其配置也相当简单,本文主要实现可以自定义多个缓存,并且针对不同缓存可以设置不同过期时间。

1.引入依赖

# gradle
implementation "com.github.ben-manes.caffeine:caffeine"

# maven
<dependency>
	<groupId>com.github.ben-manes.caffeine</groupId>
	<artifactId>caffeine</artifactId>
</dependency>

2.缓存常量CacheConstants

这里我把公共的常量提取一层,复用

public class CacheConstants {
    /**
     * 默认过期时间(配置类中我使用的时间单位是秒,所以这里如 3*60 为3分钟)
     */
    public static final int DEFAULT_EXPIRES = 3 * 60;
    public static final int EXPIRES_5_MIN = 5 * 60;
    public static final int EXPIRES_10_MIN = 10 * 60;

    public static final String GET_MENU = "GET:MENU:";
    public static final String GET_MENU_LIST = "GET:MENU:LIST:";
}

2.缓存枚举类CacheEnum

自定义缓存名称并添加到枚举中

public enum CacheEnum {

    /**
     * 获取菜单
     */
    GET_MENU(CacheConstants.GET_MENU, CacheConstants.EXPIRES_5_MIN),
    /**
     * 获取菜单列表
     */
    GET_MENU_LIST(CacheConstants.GET_MENU_LIST, CacheConstants.EXPIRES_10_MIN),
    ;
    /**
     * 缓存名称
     */
    private final String name;
    /**
     * 过期时间
     */
    private final int expires;

    /**
     * 构造
     */
    CacheEnum(String name, int expires) {
        this.name = name;
        this.expires = expires;
    }

    public String getName() {
        return name;
    }

    public int getExpires() {
        return expires;
    }
}

3.缓存配置类CacheConfig

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
public class CacheConfig {
    /**
     * Caffeine配置说明:
     * initialCapacity=[integer]: 初始的缓存空间大小
     * maximumSize=[long]: 缓存的最大条数
     * maximumWeight=[long]: 缓存的最大权重
     * expireAfterAccess=[duration]: 最后一次写入或访问后经过固定时间过期
     * expireAfterWrite=[duration]: 最后一次写入后经过固定时间过期
     * refreshAfterWrite=[duration]: 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存
     * weakKeys: 打开key的弱引用
     * weakValues:打开value的弱引用
     * softValues:打开value的软引用
     * recordStats:开发统计功能
     * 注意:
     * expireAfterWrite和expireAfterAccess同事存在时,以expireAfterWrite为准。
     * maximumSize和maximumWeight不可以同时使用
     * weakValues和softValues不可以同时使用
     */
    @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);
        return cacheManager;
    }
}

4.项目中使用

在项目中和其它本地缓存一样使用方式,用spring自带的缓存注解,简洁易懂。

	/**
     * Cacheable
     * value:缓存key的前缀。
     * key:缓存key的后缀。
     * sync:设置如果缓存过期是不是只放一个请求去请求数据库,其他请求阻塞,默认是false(根据个人需求)。
     * unless:不缓存空值,这里不使用,会报错
     */
	@Cacheable(value = CacheConstants.GET_MENU, key = "#code", sync = true)
    public MenuVO getMenu(String code) {
    	//业务代码
    }

	@Cacheable(value = CacheConstants.GET_MENU_LIST, key = "#page+':'+#pageSize", sync = true)
    public PaginationResult<MenuVO> getMenuList(Integer page, Integer pageSize) {
    	//业务代码
    }

缓存失效也是一样的,可以同时失效多个,也可以失效一个,这里举例多个。一样使用自带的注解,其它操作就不一一列举了。

 @Caching(evict = {
            @CacheEvict(value = CacheConstants.GET_MENU_LIST, allEntries = true),
            @CacheEvict(value = CacheConstants.GET_MENU, key = "#code")
    })
    public Boolean delete(String code) {
		//删除业务代码
	}

5.使用 CacheUtil 工具类

如果你不想使用 spring 自带注解,你也可以自己加个工具类操作缓存,如下:

import java.util.Objects;
import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;

@Component
public class CacheUtil {

    @Autowired
    private CacheManager cacheManager;

    private static CacheManager cm;

    @PostConstruct
    public void init() {
        cm = cacheManager;
    }

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

    /**
     * 获取缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @return
     */
    public static Object get(String cacheName, String key) {
        Cache cache = cm.getCache(cacheName);
        if (cache == null) {
            return null;
        }
        return Objects.requireNonNull(cache.get(key)).get();
    }

    /**
     * 获取缓存(字符串)
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @return
     */
    public static String getString(String cacheName, String key) {
        Cache cache = cm.getCache(cacheName);
        if (cache == null) {
            return null;
        }
        Cache.ValueWrapper wrapper = cache.get(key);
        if (wrapper == null) {
            return null;
        }
        return Objects.requireNonNull(wrapper.get()).toString();
    }

    /**
     * 获取缓存(泛型)
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @param clazz     缓存类
     * @param <T>       返回值泛型
     * @return
     */
    public static <T> T get(String cacheName, String key, Class<T> clazz) {
        Cache cache = cm.getCache(cacheName);
        if (cache == null) {
            return null;
        }
        Cache.ValueWrapper wrapper = cache.get(key);
        if (wrapper == null) {
            return null;
        }
        return (T) wrapper.get();
    }

    /**
     * 失效缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     */
    public static void evict(String cacheName, String key) {
        Cache cache = cm.getCache(cacheName);
        if (cache != null) {
            cache.evict(key);
        }
    }
}

工具类项目中使用:

@Service
public class AService {
    public void AMethod(){
        //添加缓存
        CacheUtil.put(CacheConstants.GET_MENU, "MANAGE_MENU", "........");
        //获取缓存
        String cacheStartTime = CacheUtil.get(CacheConstants.GET_MENU, "MANAGE_MENU", String.class);
        //失效缓存
        CacheUtil.evict(CacheConstants.GET_MENU, "MANAGE_MENU");
    }
}
 类似资料: