现在有这么一个业务,查看当前是第几周,理所当然,我想把它配置为LoadingCache缓存,这个缓存是没有put的,只是需要周一0时时更新一下就行,我本着不写额外定时器的想法,想直接在LoadingCache中直接动态的获取缓存过期时间,即缓存更新时间到周一0时的时间。
我以为这样,当到了周一0时,要更新缓存,这个方法会被调用,所以当更新缓存时,它的过期时间也更改为到第三周周一的0时,结果,服务上线时,出大问题(ノ=Д=)ノ┻━┻。
代码如下:
@Bean("weekCache")
public LoadingCache<String,Object> whichWeek(){
int min = DateConvert.cacheMin(); //这里是求当前时间到周一0时的分钟数
return Caffeine.newBuilder()
.expireAfterWrite((min + 1), TimeUnit.MINUTES) //缓存时间为当前时间到下周一的0点出几秒
.build(new CacheLoader<String, Object>() {
@Override
public @Nullable Object load(String key) throws Exception {
if (key.equals("week")){
Integer week = infoMapper.getWeekByToday();
return week;
}
return null;
}
});
}
我在int min = DateConvert.cacheMin();
下面打印了输出语句,结果发现,当缓存更新与否,都不会输出。
结论:
LoadingCache
更新缓存时,只是再次调用return
而已,并不是调用整个方法。
我想,既然方法不被调用,那我把DateConvert.cacheMin()
直接写在expireAfterWrite
里总应该行了吧?于是…
更改后的代码:
@Bean("weekCache")
public LoadingCache<String,Object> whichWeek(){
return Caffeine.newBuilder()
.expireAfterWrite((DateConvert.cacheMin() + 1), TimeUnit.MINUTES) //缓存更新为下周一的0时出几秒
.build(new CacheLoader<String, Object>() {
@Override
public @Nullable Object load(String key) throws Exception {
if (key.equals("week")){
Integer week = infoMapper.getWeekByToday();
return week;
}
return null;
}
});
}
结果就是仍然不行。
个人猜想原因:缓存更新时,只是重新调用
.build()
方法,而.expireAfterWrite()
的值在首次加载时就确定的,所以之后尽管更新之后,缓存用的也是第一次时的缓存过期时间。
老老实实写个定时器,貌似LoadingCache
不支持动态更新缓存过期时间。
@Resource(name = "weekCache")
LoadingCache<String,Object> weekCache;
@Scheduled(cron = "1 0 0 ? * MON") //星期一0点1秒
public void updateCurrentWeek(){
Integer week = infoMapper.getWeekByToday();
weekCache.put("week",week);
}