SpringBoot使用caffeine本地缓存

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

使用 Caffeine 方法实现缓存

引入相关依赖

<!-- caffeine cache -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.0.5</version>
</dependency>

本地缓存配置类CacheConfig

@Configuration
public class CacheConfig {

    @Bean
    public Cache caffeineCache() {
        return Caffeine.newBuilder()
            // 设置最后一次写入或访问后经过固定时间过期
            .expireAfterWrite(60, TimeUnit.SECONDS)
            // 初始的缓存空间大小
            .initialCapacity(100)
            // 缓存的最大条数
            .maximumSize(1000)
            .build();
    }
}

控制层接口

@RestController
@RequestMapping("/cache")
public class CacheController {

    @Autowired
    Cache<String, Object> caffeineCache;

    /**
     * 加入缓存
     *
     * @return
     */
    @GetMapping("/setSession/{id}")
    public String setSession(@PathVariable String id) {
        System.out.println("create");
        // 加入缓存(key不存在则新增,存在则更新)
        caffeineCache.put(id, "13123123");
        return "success";
    }

    /**
     * 获取缓存
     *
     * @return
     */
    @GetMapping("/getSession/{id}")
    public String getSessionId(@PathVariable String id) {
        System.out.println("get");
        // 获取缓存
        caffeineCache.getIfPresent(id);
        return (String) caffeineCache.asMap().get(id);
    }
}

使用 SpringCache 注解方法实现缓存

引入caffeine依赖pom

<!-- cache -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- caffeine cache -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.0.5</version>
</dependency>

本地缓存配置类CacheConfig

@Configuration
public class CacheConfig {

    /**
     * 配置缓存管理器
     * @return 缓存管理器
     */
    @Bean("caffeineCacheManager")
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
                // 最后一次写入后经过固定时间过期300秒
                .expireAfterWrite(300, TimeUnit.SECONDS)
                // 初始的缓存空间大小
                .initialCapacity(100)
                // 缓存的最大条数
                .maximumSize(1000));
        return cacheManager;
    }
}

在需要缓存的类和方法上添加@EnableCaching和@Cacheable

1)接口类InterlibService

public interface InterlibService {
    /**
     * 获取interlib的SessionId
     * @return
     */
    Result<String> getSessionId();
}

2)实现类InterlibServiceImpl

@Service("interlibService")
@EnableCaching
public class InterlibServiceImpl implements InterlibService {

    @Override
    @Cacheable(cacheNames = "caffeineCacheManager", key = "#root.targetClass.simpleName+'-getSessionId'", unless = "!#result.success")
    public Result<String> getSessionId() {
    	System.out.println("获取数据");
    	return new Result(200, "查询成功", "12321312");
    }
}

3)统一响应实体类Result

/**
 * 统一API响应结果封装
 */
public class Result<T> {
    /**
     * 响应编号,参考ResultCode
     */
    private int code;
    /**
     * 消息
     */
    private String message;
    /**
     * 数据
     */
    private T data;

    private Boolean success;
    
    public Result(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
        this.success = isSuccess();
    }
    public boolean isSuccess() {
        return this.code == 200;
    }
}

控制层接口

@RestController
@RequestMapping("/interlib")
public class InterlibController {

    @Autowired
    private InterlibService interlibService;

    /**
     * 获取interlib的SessionId信息
     * @return
     */
    @GetMapping("/getSession")
    public Result<String> getSessionId() {
        return interlibService.getSessionId();
    }
}

caffeine配置说明

参数 类型 描述
initialCapacity int 初始的缓存空间大小
maximumSize long 缓存的最大条数
maximumWeight long 缓存的最大权重
expireAfterWrite 或 expireAfterAccess duration 最后一次写入或访问后经过固定时间过期
refreshAfterWrite duration 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存
weakKeys boolean 打开 key 的弱引用
weakValues boolean 打开 value 的弱引用
softValues boolean 打开 value 的软引用
recordStats   开发统计功能

备注:

  • weakValues 和 softValues 不可以同时使用。
  • maximumSize 和 maximumWeight 不可以同时使用。
  • expireAfterWrite 和 expireAfterAccess 同时存在时,以 expireAfterWrite 为准。

Spring Cache注解说明

注解 说明
@Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@CachePut 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
@CachEvict 主要针对方法配置,能够根据一定的条件对缓存进行清空
@CacheConfig 所有的@Cacheable()里面都有一个value=“xxx”的属性,CacheConfig主要针对类配置,如果你在你的方法写别的名字,那么依然以方法的名字为准。
@EnableCaching 注解是spring framework中的注解驱动的缓存管理功能。自spring版本3.1起加入了该注解。如果你使用了这个注解,那么你就不需要在XML文件中配置cache manager了。可以加在启动类上,也可以加在配置类上,还可以加在缓存实现类上。主要加在启动类上。
@Caching 有时候我们可能组合多个Cache注解使用;比如用户新增成功后,我们要添加id–>user;username—>user;email—>user的缓存;此时就需要@Caching组合多个注解标签了。
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")
})
public User save(User user) {
}

自定义缓存注解

之前的那个@Caching组合,会让方法上的注解显得整个代码比较乱,此时可以使用自定义注解把这些注解组合到一个注解中,如:

@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.username"),
@CachePut(value = "user", key = "#user.email")
})
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface UserSaveCache {
}

这样我们在方法上使用如下代码即可,整个代码显得比较干净。

@UserSaveCache
public User save(User user)

注解参数

参数名 说明
value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存
unless 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 false 才进行缓存
cacheNames 指定配置
allEntries 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存
beforeInvocation 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存

SpEL上下文数据

名称 位置 描述 示例
methodName root对象 当前被调用的方法名 root.methodName
method root对象 当前被调用的方法 root.method.name
target root对象 当前被调用的目标对象 root.target
targetClass root对象 当前被调用的目标对象类 root.targetClass
args root对象 当前被调用的方法的参数列表 root.args[0]
caches root对象 当前方法调用使用的缓存列表(如@Cacheable(value={“cache1”, “cache2”})),则有两个cache root.caches[0].name
argument name 执行上下文 当前被调用的方法的参数,如findById(Long id),我们可以通过#id拿到参数 user.id
result 执行上下文 方法执行后的返回值(仅当方法执行之后的判断有效,如‘unless’,’cache evict’的beforeInvocation=false) result

 

posted @ 2022-04-24 14:25  残城碎梦  阅读(2408)  评论(0编辑  收藏  举报