java - Spring 可缓存异步更新,同时返回旧缓存
问题描述
有休息控制器,它@Cacheable
从@Service
. 我的CacheManager
有expireAfterWrite
超时,所以当超时后使用rest->服务方法时,必须重写缓存。但问题是,如果同时有许多 rest 调用,所有调用的线程都会转到服务方法并重写缓存。我需要通过 进行服务方法同步@Cacheable(sync=true)
,但其他调用必须在第一次调用创建新缓存时返回旧缓存。
package application.system.config;
import com.google.common.cache.CacheBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
public class CacheManagerConfiguration {
@Value("${cache.timer.timeout}")
private int cacheTimeout;
@Bean("timeOutCacheManager")
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager() {
@Override
protected Cache createConcurrentMapCache(String name) {
return new ConcurrentMapCache(
name,
CacheBuilder.newBuilder()
.expireAfterWrite(cacheTimeout, TimeUnit.SECONDS)
.build().asMap(), false);
}
};
}
}
@GetMapping(RestEndpoints.GET_SCHEDULE)
public ResponseEntity<SummaryReport> getSchedule(@RequestParam(required = false) String department,
@RequestParam(required = false) Long group) throws InterruptedException {
return ResponseEntity.ok(scheduleService.getSummaryReport(department, group));
}
@Transactional
@Cacheable(value = Caches.SUMMARY_REPORT, condition = "#root.target.isCacheEnable", sync = true)
public SummaryReport getSummaryReport(String department, Long group) {
SummaryReport report = new SummaryReport() {{
setDepartments(new ArrayList<>());
}};
List<DepartmentTable> departmentEntities = getDepartmentsData(department);
List<ScheduleTable> scheduleEntities = getSchedulesData(department, group);
List<ConstraintTable> constraintEntities = getConstraintsData(department, group);
departmentEntities.forEach(departmentEntity -> {
List<ScheduleTable> departmentsSchedules = scheduleEntities
.stream()
.filter(schedule -> schedule.getEnable() == 1)
.filter(schedule -> schedule.getDepartmentTableRef().getId().equals(departmentEntity.getId()))
.collect(Collectors.toList());
List<ConstraintTable> departmentsConstraintsEntities = constraintEntities
.stream()
.filter(entity -> entity.getDepartmentTableRef().getId().equals(departmentEntity.getId()))
.collect(Collectors.toList());
reportHandler.addDepartmentToReport(report, departmentEntity, departmentsSchedules, departmentsConstraintsEntities);
});
LOGGER.info("Caches were expired, actual data was obtained by {}", getCurrentApp());
return report;
}
解决方案
推荐阅读
- terraform - 使用 Terraform 创建 ALb 时如何解决未找到证书的问题?
- javascript - Javascript .$inject 方法
- keras - 如何使用 tensorflow keras 导入分割模型?获取 ModuleNotFoundError:没有名为 'keras.legacy' 的模块
- asp.net-mvc - 如何在一个域下托管两个应用程序
- azure-devops - 无法在 Azure DevOps 管道中生成项目
- python - Pandas:如何根据条件替换数据框中的值
- firebase - Flutter Firebase - 检索数组和地图数据
- php - 将第一个 SQL 选择语句结果用于第二个选择语句
- selenium - 在 URL 2 中使用查找元素时遇到问题
- python-3.x - Flask 版本不兼容问题