1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.7.0</version>
</dependency>
2.配置类
package com.chaos.celery.config;
import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
/**
* 本地缓存
*/
@Configuration
public class CaffeineCacheConfig {
//配置CacheManager
@Bean(name = "caffeineCacheManager")
public CacheManager cacheManagerWithCaffeine(@Qualifier("cacheLoader") CacheLoader cacheLoader) {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
Caffeine caffeine = Caffeine.newBuilder()
//cache的初始容量值
.initialCapacity(100)
//maximumSize用来控制cache的最大缓存数量,maximumSize和maximumWeight(最大权重)不可以同时使用,
.maximumSize(1000)
//最后一次写入或者访问后过久过期
.expireAfterAccess(500, TimeUnit.SECONDS)
//创建或更新之后多久刷新,需要设置cacheLoader
.refreshAfterWrite(10, TimeUnit.SECONDS);
cacheManager.setCaffeine(caffeine);
cacheManager.setCacheLoader(cacheLoader);
//cacheManager.setCacheNames(names);//根据名字可以创建多个cache,但是多个cache使用相同的策略
cacheManager.setAllowNullValues(false);//是否允许值为空
return cacheManager;
}
@Bean("caffeineCache")
public LoadingCache getCache(@Qualifier("cacheLoader") CacheLoader cacheLoader) {
return Caffeine.newBuilder()
//cache的初始容量值
.initialCapacity(100)
//maximumSize用来控制cache的最大缓存数量,maximumSize和maximumWeight(最大权重)不可以同时使用,
.maximumSize(1000)
//最后一次写入或者访问后过久过期
.expireAfterAccess(500, TimeUnit.SECONDS)
//创建或更新之后多久刷新,需要设置cacheLoader
.refreshAfterWrite(10, TimeUnit.SECONDS).build(cacheLoader);
}
/**
* 必须要指定这个Bean,refreshAfterWrite配置属性才生效
*/
@Bean(name = "cacheLoader")
public CacheLoader<Object, Object> cacheLoader() {
return new CacheLoader<Object, Object>() {
//第一次请求访问这个方法,这时缓存为空,可以在这时去请求数据库填满缓存
@Override
public Object load(Object key) throws Exception {
return null;
}
// 过期刷新缓存是回调这个方法,这时候应该去请求数据库可以根据自己的需需求设计缓存对象或以map形式保存,然后在key过期时去请求数据库刷新缓存对象或map
@Override
public Object reload(Object key, Object oldValue) throws Exception {
System.out.println("--refresh--:" + key);
return oldValue;
}
};
}
}
3.使用
@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserService userService;
@Autowired
private Cache caffeineCache;
/**
*put操作:put当前的缓存项,并启动一个线程去后台执行过期缓存项的移除任务。
get操作:如果发现cache中有过期缓存项,则启动一个线程去后台执行这些缓存项的移除任务,如果get的正好是过期的缓存项,则当前线程会马上执行load方法,直到load方法加载完毕,get方法返回。
getIfPresent操作:如果发现cache中有过期缓存项,则启动一个线程去后台执行这些缓存项的移除任务,如果getIfPresent的正好是过期的缓存项,则当前线程马上返回null。
*
*/
@PostMapping("/getUser")
@Cacheable(cacheNames = "findUserById", key = "#id", cacheManager = "caffeineCacheManager")
public User findUserById(@RequestParam int id){
if (caffeineCache.get("user" + id) == null){
User user = userService.findById(id);
caffeineCache.put("user" + id, user);
return user;
}else{
return caffeineCache.get("user" + id);
}
}
}