项目中用到了本地缓存CaffeineCache,在这里简单介绍一下使用方法。
缓存配置有两种:SimpleCacheManager和CaffeineCacheManager
它们配置的区别如下:
当应用程序启动时,通过配置多个CaffeineCache来创建多个缓存。可以为每个方法单独配置缓存过期时间。
使用一个全局的Caffeine配置,来创建所有的缓存。不能为每个方法,单独配置缓存过期时间,但可以在程序启动时,
全局的配置缓存,方便设置所有方法的缓存过期时间。
如果想要每个方法单独配置缓存过期时间,使用第一种方式。否则,想全局设置的缓存配置,使用第二种方式。
<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>
<version>2.6.2</version>
</dependency>
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
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;
/**
* 缓存配置有两种:SimpleCacheManager和CaffeineCacheManager
* 它们配置的区别如下:
* <p>
* SimpleCacheManager:
* 当应用程序启动时,通过配置多个CaffeineCache来创建多个缓存。可以为每个方法单独配置缓存过期时间。
* <p>
* CaffeineCacheManager:
* 使用一个全局的Caffeine配置,来创建所有的缓存。不能为每个方法,单独配置缓存过期时间,但可以在程序启动时,
* 全局的配置缓存,方便设置所有方法的缓存过期时间。
* <p>
* 总结:
* 如果想要每个方法单独配置缓存过期时间,建议使用第一种方式。
* 否则,你想设置全局的缓存配置,建议使用第二种方式。
*/
@EnableCaching
@Configuration
public class SimpleCaffeineConfig {
// /**
// * 写法一:初始化SimpleCacheManager管理器
// * @return
// */
// @Bean
// @Primary
// public CacheManager simpleCacheManager() {
// SimpleCacheManager cacheManager = new SimpleCacheManager();
// ArrayList<CaffeineCache> caches = new ArrayList<>();
// Map<String, Object> map = putCacheRule();
// for (String name : map.keySet()) {
// caches.add(new CaffeineCache(name, (Cache<Object, Object>) map.get(name)));
// }
// cacheManager.setCaches(caches);
// return cacheManager;
// }
//
// /**
// * 配置多个缓存
// *
// * @return
// */
// private static Map<String, Object> putCacheRule() {
// Map<String, Object> map = new ConcurrentHashMap<>();
// map.put("caffeine_test_1", Caffeine.newBuilder().recordStats()
// .expireAfterWrite(1, TimeUnit.MINUTES)
.maximumSize(10000)
// .build());
// map.put("caffeine_test_2", Caffeine.newBuilder().recordStats()
// .expireAfterWrite(2, TimeUnit.HOURS)
.maximumSize(10000)
// .build());
// return map;
// }
/**
* 写法二:初始化SimpleCacheManager管理器
*
* @return
*/
@Bean
public CacheManager caffeineCacheManager() {
SimpleCacheManager cacheManager = new SimpleCacheManager();
List<CaffeineCache> caches = new ArrayList<>();
//缓存一:失效时间是1分钟
caches.add(new CaffeineCache("simple_caffeine_test_1",
Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build()));
//缓存二:失效时间是1小时
caches.add(new CaffeineCache("simple_caffeine_test_2",
Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build()));
cacheManager.setCaches(caches);
return cacheManager;
}
}
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
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;
/**
* 缓存配置有两种:SimpleCacheManager和CaffeineCacheManager
* 它们配置的区别如下:
* <p>
* SimpleCacheManager:
* 当应用程序启动时,通过配置多个CaffeineCache来创建多个缓存。可以为每个方法单独配置缓存过期时间。
* <p>
* CaffeineCacheManager:
* 使用一个全局的Caffeine配置,来创建所有的缓存。不能为每个方法,单独配置缓存过期时间,但可以在程序启动时,
* 全局的配置缓存,方便设置所有方法的缓存过期时间。
* <p>
* 总结:
* 如果想要每个方法单独配置缓存过期时间,建议使用第一种方式。
* 否则,你想设置全局的缓存配置,建议使用第二种方式。
*/
@EnableCaching
@Configuration
public class CaffeineCacheConfig {
@Bean
public CacheManager caffeineCacheManager() {
CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
Caffeine<Object, Object> caffeine = Caffeine.newBuilder()
// 初始大小
.initialCapacity(10)
// 最大容量
.maximumSize(100)
// 打开统计
.recordStats()
// 5分钟不访问自动丢弃
.expireAfterAccess(5, TimeUnit.MINUTES);
caffeineCacheManager.setCaffeine(caffeine);
// 设定缓存器名称
caffeineCacheManager.setCacheNames(getKeys());
// 值不可为空
caffeineCacheManager.setAllowNullValues(false);
return caffeineCacheManager;
}
/**
* 配置缓存key
*
* @return
*/
public static List<String> getKeys() {
List<String> names = new ArrayList<>(1);
names.add("cache_caffeine_test_1");
return names;
}
}
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.UUID;
/**
* @Author:
* @Description
* @Date: 上午9:32 2024/1/16
*/
@Service
public class CaffeineService {
/**
* 方式一:SimpleCacheManager
* <p>
* 注解的参数包括:
* <p>
* cacheNames:指定缓存的名称。
* key:指定缓存的 key。这里的 key 是一个 SpEL 表达式,表示使用方法的参数,作为 key。
* unless:指定当方法的返回值为 null 时,不将结果缓存。
* unless这个注解的作用是,当调用这个方法时,会先在本地缓存中查找是否已经缓存了结果,如果有,则直接返回缓存中的结果;
* 如果没有,则执行方法体,并将方法的返回值缓存到本地缓存中,供下次使用。如果方法的返回值为 null,则不会将结果缓存。
* <p>
*
* @param name
* @param address
* @return
*/
// @Cacheable(value = "simple_caffeine_test_1", key = "#root.methodName+'_'+#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
@Cacheable(value = "simple_caffeine_test_1", key = "#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
public String testSimpleCaffeine(String name, String address) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return name + address;
}
/**
* 更新缓存
*/
@CachePut(value = "simple_caffeine_test_1", key = "#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
public String update(String name, String address) {
return name + address+ UUID.randomUUID().toString();
}
/**
* 删除缓存
*/
@CacheEvict(value = "simple_caffeine_test_1", key = "#root.args[0]+'_'+#root.args[1]")
public String del(String name, String address) {
return "";
}
/**
* 方式二:CaffeineCacheManager
*
* @param name
* @param address
* @return
*/
@Cacheable(value = "cache_caffeine_test_1", key = "#root.methodName+'_'+#root.args[0]+'_'+#root.args[1]", unless = "#result == null")
public String testCacheCaffeine(String name, String address) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return name + address;
}
}
import com.example.service.CaffeineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author:
* @Description
* @Date: 上午9:32 2024/1/16
*/
@RestController
@RequestMapping("/caffeine")
public class CaffeineController {
@Autowired
private CaffeineService caffeineService;
@GetMapping("/simple")
public String testSimpleCaffeine(String name, String address){
return caffeineService.testSimpleCaffeine(name,address);
}
@GetMapping("/update")
public String testUpdate(String name, String address){
return caffeineService.update(name,address);
}
@GetMapping("/del")
public String testDel(String name, String address){
return caffeineService.del(name,address);
}
@GetMapping("/cache")
public String testCacheCaffeine(String name, String address){
return caffeineService.testCacheCaffeine(name,address);
}
}
注意:SimpleCaffeineConfig和CaffeineCacheConfig必须注释掉其中一个类,来分别测试
1、启动项目,这里以SimpleCaffeine方式进行测试
2、模拟加入缓存,地址栏输入:localhost:8077/caffeine/simple?name=111&address=222 等待三秒数据返回
3、继续操作第2步,这时候看到数据返回需要6毫秒,缓存生效
4、模拟数据更新,地址栏输入:localhost:8077/caffeine/update?name=111&address=222
5、模拟读取缓存更新后的数据,地址栏输入:localhost:8077/caffeine/simple?name=111&address=222 看到数据已更新,且数据返回需要5毫秒,缓存更新生效
6、模拟清空缓存,地址栏输入:localhost:8077/caffeine/del?name=111&address=222 ,然后地址栏输入:localhost:8077/caffeine/simple?name=111&address=222 返回数据需要3.15秒,缓存清空生效