spring-boot - Spring Boot Native 缓存:如何通过单个键/元素过期/删除缓存数据
问题描述
我们正在调用身份联合服务以非常频繁地获取用户令牌,并且几乎在身份服务上运行负载测试。
一个潜在的解决方案是在现有应用程序中缓存用户令牌,但是使用本机 spring-cache,我们可以使单个缓存条目过期吗?
在下面的示例中,我能够清除缓存,删除所有条目,但是我试图使单个条目过期。
@Service
@CacheConfig(cacheNames = {"userTokens"})
public class UserTokenManager {
static HashMap<String, String> userTokens = new HashMap<>();
@Cacheable
public String getUserToken(String userName){
String userToken = userTokens.get(userName);
if(userToken == null){
// call Identity service to acquire tokens
System.out.println("Adding UserName:" + userName + " Token:" + userToken);
userTokens.put(userName, userToken);
}
return userToken;
}
@CacheEvict(allEntries = true, cacheNames = { "userTokens"})
@Scheduled(fixedDelay = 3600000)
public void removeUserTokens() {
System.out.println("##############CACHE CLEANING##############, " +
"Next Cleanup scheduled at : " + new Date(System.currentTimeMillis()+ 3600000));
userTokens.clear();
}
}
Spring-boot 应用类如下:
@SpringBootApplication
@EnableCaching
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
解决方案
@CacheEvict
您可以使用获取缓存键的方法使单个缓存条目过期。此外,通过使用 Spring 的缓存和@Cacheable
,不需要 HashMap 代码(因为这实际上只是一个二级缓存)。
简单缓存
@Service
@CacheConfig(cacheNames = {"userTokens"})
public class UserTokenManager {
private static Logger log = LoggerFactory.getLogger(UserTokenManager.class);
@Cacheable(cacheNames = {"userTokens"})
public String getUserToken(String userName) {
log.info("Fetching user token for: {}", userName);
String token = ""; //replace with call for token
return token;
}
@CacheEvict(cacheNames = {"userTokens"})
public void evictUserToken(String userName) {
log.info("Evicting user token for: {}", userName);
}
@CacheEvict(cacheNames = {"userTokens"}, allEntries = true)
public void evictAll() {
log.info("Evicting all user tokens");
}
}
例如:
getUserToken("Joe") -> no cache, calls API
getUserToken("Alice") -> no cache, calls API
getUserToken("Joe") -> cached
evictUserToken("Joe") -> evicts cache for user "Joe"
getUserToken("Joe") -> no cache, calls API
getUserToken("Alice") -> cached (as it has not been evicted)
evictAll() -> evicts all cache
getUserToken("Joe") -> no cache, calls API
getUserToken("Alice") -> no cache, calls API
基于 TTL 的缓存
如果你希望你的令牌被缓存一段时间,CacheManager
除了原生的 Spring 令牌之外,你还需要另一个令牌。有多种缓存选项可以与 Spring 的@Cacheable
. 我将举一个使用 Caffeine 的示例,它是 Java 8 的高性能缓存库。例如,如果您知道要缓存 30 分钟的令牌,您可能会选择这条路线。
首先,将以下依赖项添加到您的build.gradle
(或者如果使用 Maven,请翻译以下内容并将其放入您的pom.xml
. 请注意,您需要使用最新版本,或者与您当前的 Spring Boot 版本匹配的版本。
compile 'org.springframework.boot:spring-boot-starter-cache:2.1.4'
compile 'com.github.ben-manes.caffeine:caffeine:2.7.0'
添加这两个依赖项后,您所要做的就是caffeine
在文件中配置规范application.properties
:
spring.cache.cache-names=userTokens
spring.cache.caffeine.spec=expireAfterWrite=30m
更改expireAfterWrite=30m
为您希望代币生存的任何价值。例如,如果您想要 400 秒,您可以将其更改为expireAfterWrite=400s
.
有用的链接:
推荐阅读
- android - 不允许加载本地资源:ionic 3 android
- android - 如何在 android studio 中发布 gradle 4.4 中的工件(将 APK 上传到 nexus)?
- android - 将 WebView 用于 android 应用程序是否安全?
- c - 如何使用 openssl 通过本地信任库验证 PEM 中的证书?
- python - 读取 netCDF 文件时缺少值“--”
- php - php --version 别名设置在 Mac 上出错
- r - XLConnect:保存工作簿更新错误
- sonarqube - SonarQube locak html 报告在新版本中不可用
- vue.js - 在子组件中使用 Vuex 观察和跟踪状态变化
- javascript - 出错后 PM2 不会重新启动我的进程