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 |