Springboot 集成 Caffeine
Caffeine 是个高性能的开源 Java 内存缓存库,具有较高的命中率和出色的并发能力。在 Spring Boot 中集成也非常简单,提供了各种开箱既用的工具。
Caffeine 并不是分布式缓存.
Springboot 中引用的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
</dependencies>
其中有两个依赖需要注意
<!-- springboot 缓存-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- caffeine 依赖-->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
配置文件
spring.cache.cache-names=IZUUL
spring.cache.caffeine.spec=initialCapacity=50,maximumSize=500,expireAfterWrite=5s
spring.cache.type=caffeine
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不可以同时使用
启动类中加入 @EnableCaching 注解 开启缓存
package com.izuul.caffeinedemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
//启用缓存
@EnableCaching
public class CaffeineDemoApplication {
public static void main(String[] args) {
SpringApplication.run(CaffeineDemoApplication.class, args);
}
}
创建 service, 其中有三个方法:
查询方法 cacheIZUUL(), 获取需要缓存的数据, 调用 getCache() 方法
修改方法 cachePutIZUUL(), 更新缓存数据
getCache() 方法模拟生产项目中的逻辑代码, 线程睡眠 3s 模拟项目运行耗时
关于@CacheAble @CachePut 等注解上以前的 <<Springboot 集成 Redis>>中有介绍
package com.izuul.caffeinedemo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class CaffeineService {
@Cacheable(value = "IZUUL", key = "#key")
public String cacheIZUUL(String key) {
log.info("cacheIZUUL()方法执行");
return getCache(key);
}
@CachePut(value = "IZUUL", key = "#key")
public String cachePutIZUUL(String key) {
log.info("cachePutIZUUL()方法执行");
return "cachePutIZUUL--" + key;
}
private String getCache(String key) {
try {
log.info("getCache()方法执行");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return key;
}
}
创建 controller 调用 service
package com.izuul.caffeinedemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CaffeineController {
@Autowired
private CaffeineService caffeineService;
@GetMapping("/cache-izuul/{key}")
public String cacheIZUUL(@PathVariable String key) {
return caffeineService.cacheIZUUL(key);
}
@GetMapping("/cache-put-izuul/{key}")
public String cachePutIZUUL(@PathVariable String key) {
return caffeineService.cachePutIZUUL(key);
}
}
启动项目 访问 http://localhost:8080/cache-izuul/izuul
延迟 3 秒后展示数据 izuul, 5s 后缓存过期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NDvCDyd6-1609982441988)(https://ws1.sinaimg.cn/large/006tNc79ly1g2txnkqlixj30bs03l3ym.jpg)]
访问 http://localhost:8080/cache-put-izuul/izuul
展示数据 cachePutIZUUL—izuul, 同样是 5s 后缓存过期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jVj2sou2-1609982441993)(https://ws3.sinaimg.cn/large/006tNc79ly1g2txva8oalj30d004qdg1.jpg)]
以上配置过程比较死板, 没法实现多种缓存策略, 所以可以在项目中手动进行配置
删除 properties 文件中的配置
创建配置类 CaffeineConfig
package com.izuul.caffeinedemo;
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 CaffeineConfig {
@Bean
public CacheManager caffeineCacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
List<CaffeineCache> caffeineCaches = new ArrayList<>();
for (CacheType cacheType : CacheType.values()) {
caffeineCaches.add(new CaffeineCache(cacheType.name(),
Caffeine.newBuilder()
.expireAfterWrite(cacheType.getExpires(), TimeUnit.SECONDS)
.build()));
}
cacheManager.setCaches(caffeineCaches);
return cacheManager;
}
}
创建枚举类, 加入过期时间expires, 分别设置IZUUl消亡时间是 10s, MUMU 消亡时间 5s
package com.izuul.caffeinedemo;
public enum CacheType {
IZUUL(10),
MUMU(5);
private int expires;
CacheType(int expires) {
this.expires = expires;
}
public int getExpires() {
return expires;
}
}
以上配置就完成了 在 service 中新增两个方法来进行验证
package com.izuul.caffeinedemo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class CaffeineService {
@Cacheable(value = "IZUUL", key = "#key")
public String cacheIZUUL(String key) {
log.info("cacheIZUUL()方法执行");
return getCache(key);
}
@CachePut(value = "IZUUL", key = "#key")
public String cachePutIZUUL(String key) {
log.info("cachePutIZUUL()方法执行");
return "cachePutIZUUL--" + key;
}
@Cacheable(value = "MUMU", key = "#key")
public String cacheMUMU(String key) {
log.info("cacheMUMU()方法执行");
return getCache(key);
}
@CachePut(value = "MUMU", key = "#key")
public String cachePutMUMU(String key) {
log.info("cachePutMUMU()方法执行");
return "cachePutMUMU--" + key;
}
private String getCache(String key) {
try {
log.info("getCache()方法执行");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return key;
}
}
controller 中调用新增的方法
package com.izuul.caffeinedemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CaffeineController {
@Autowired
private CaffeineService caffeineService;
@GetMapping("/cache-izuul/{key}")
public String cacheIZUUL(@PathVariable String key) {
return caffeineService.cacheIZUUL(key);
}
@GetMapping("/cache-put-izuul/{key}")
public String cachePutIZUUL(@PathVariable String key) {
return caffeineService.cachePutIZUUL(key);
}
@GetMapping("/cache-mumu/{key}")
public String cacheMUMU(@PathVariable String key) {
return caffeineService.cacheMUMU(key);
}
@GetMapping("/cache-put-mumu/{key}")
public String cachePutMUMU(@PathVariable String key) {
return caffeineService.cachePutMUMU(key);
}
}
添加完成后 启动项目, 分别访问 http://localhost:8080/cache-izuul/izuul 和 http://localhost:8080/cache-mumu/mumu
你会发现 cahce-izuul 经过 10s 后会再一次执行 getCache() 方法, 说明它的缓存有 10s
而 cahce-mumu 是 5s
以上证明我们手动配置的 Caffeine 缓存策略成功了
在 java 项目中可以使用此方法进行本地缓存