在应用程序启动时缓存查找并不起作用

时间:2018-02-02 10:31:51

标签: java spring tomcat spring-boot spring-cache

我在 tomcat 9.0.2 上使用 Spring Boot 1.5.9 ,我正在尝试使用spring @Cacheable 调度a来缓存查找在应用程序启动时运行的缓存刷新作业,每24小时重复一次,如下所示:

@Component
public class RefreshCacheJob {

    private static final Logger logger = LoggerFactory.getLogger(RefreshCacheJob.class);

    @Autowired
    private CacheService cacheService;

    @Scheduled(fixedRate = 3600000 * 24, initialDelay = 0)
    public void refreshCache() {
        try {
            cacheService.refreshAllCaches();
        } catch (Exception e) {
            logger.error("Exception in RefreshCacheJob", e);
        }
    }

}

,缓存服务如下:

@Service
public class CacheService {

    private static final Logger logger = LoggerFactory.getLogger(CacheService.class);

    @Autowired
    private CouponTypeRepository couponTypeRepository;

    @CacheEvict(cacheNames = Constants.CACHE_NAME_COUPONS_TYPES, allEntries = true)
    public void clearCouponsTypesCache() {}

    public void refreshAllCaches() {
        clearCouponsTypesCache();
        List<CouponType> couponTypeList = couponTypeRepository.getCoupons();
        logger.info("######### couponTypeList: " + couponTypeList.size());
    }
}

存储库代码:

public interface CouponTypeRepository extends JpaRepository<CouponType, BigInteger> {
    @Query("from CouponType where active=true and expiryDate > CURRENT_DATE order by priority")
    @Cacheable(cacheNames = Constants.CACHE_NAME_COUPONS_TYPES)
    List<CouponType> getCoupons();
}

稍后在我的网络服务中,尝试按如下方式进行查找:

@GET
@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
@Path("/getCoupons")
@ApiOperation(value = "")
public ServiceResponse getCoupons(@HeaderParam("token") String token, @HeaderParam("lang") String lang) throws Exception {
    try {
        List<CouponType> couponsList = couponRepository.getCoupons();
        logger.info("###### couponsList: " + couponsList.size());
        return new ServiceResponse(ErrorCodeEnum.SUCCESS_CODE, resultList, errorCodeRepository, lang);
    } catch (Exception e) {
        logger.error("Exception in getCoupons webservice: ", e);
        return new ServiceResponse(ErrorCodeEnum.SYSTEM_ERROR_CODE, errorCodeRepository, lang);
    }
}

第一次调用它从数据库获取查询以及后续调用从缓存中获取它,而它应该在Web服务的第一次调用中从缓存中获取它?

请告知我为什么会遇到这种行为以及如何解决此问题。

3 个答案:

答案 0 :(得分:2)

升级到 Tomcat 9.0.4

后问题已解决

答案 1 :(得分:1)

虽然它不会影响计划任务本身,但在CacheService中调用@CacheEvict时,clearCouponsTypesCache()上的List<CouponType> couponTypeList = couponTypeRepository.getCoupons(); 被绕过,因为它是从同一个类调用的(见this回答)。它将导致缓存未被清除

@Cacheable

被调用。这意味着getCoupons() @CacheEvict方法不会查询数据库,而是返回缓存中的值。

这使得计划缓存刷新操作仅在缓存为空时才能正常工作一次。之后它没用了。

refreshAllCaches()注释应移至beforeInvocation=true方法并向其添加@Cacheable参数,以便在填充之前清除缓存,而不是之后。

此外,使用Spring 4 / Spring Boot 1.X时,应考虑这些错误:

虽然此错误似乎不会影响此特定程序,但将JpaRepository注释与{{1}}接口分开,直到迁移到Spring 5 / Spring Boot 2.X可能是个好主意。< / p>

答案 2 :(得分:0)

在同一服务中调用时,

@CacheEvict不会被调用。这是因为Spring在服务周围创建了一个代理服务器,只能从&#34;外部&#34;浏览缓存代理。

解决方案是添加

@CacheEvict(cacheNames = Constants.CACHE_NAME_COUPONS_TYPES, allEntries = true)

refreshAllCaches,或将refreshAllCaches移至调用ICacheService.clearCouponsTypeCache的新服务。