确保始终从Spring应用程序中的缓存中检索数据

Ale*_*ian 4 java spring ehcache

在使用Spring Framework构建的Java EE应用程序中,我需要在DAO中执行一些非常昂贵的操作,这可能需要几分钟的时间.使用Spring MVC,当用户的请求映射到控制器方法时,我通过我的Controller命中DAO:

@RequestMapping(value = "/categories.do")
public ModelAndView categories(
        @PathVariable("cc") String cc,
        @PathVariable("ll") String ll) {
    Locale locale = new Locale(ll, cc);
    ModelAndView result = getView("categories", locale);
    Map<Category, List<Product>> allProducts = supplyDao.getAllProducts(locale);
    result.addObject("products", allProducts);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

getAllProducts方法向外部Web服务发出大量请求以绘制产品所需的所有数据.该方法通过Spring的@Cacheable注释缓存在底层Ehcache实现上:

@Cacheable(value = CACHE_NAME, key = CACHE_KEY_PREFIX + "'(' + #p0 + ')'")
public Map<Category, List<Product>> getAllProducts(Locale locale) {
        // a lot of HTTP requests firing from here
}
Run Code Online (Sandbox Code Playgroud)

这种方法的问题在于,当缓存为空时,页面基本上是不可访问的.此外,如果在缓存为空时多个请求命中页面,则DAO方法将再次触发,并且所有请求将并行重复.据我所知,第二个问题的解决方案是使用a BlockingCache,但我还没有机会实现它.

我想要的是让控制器方法始终从缓存中提取结果.我想实现一个@PostConstruct触发所有语言环境的缓存填充的方法.就像是:

@PostConstruct
public void populateCaches() {
    for (Locale locale : localeList) {
        getAllProducts(locale);
    }
}
Run Code Online (Sandbox Code Playgroud)

我不介意初始人口需要一段时间,因为服务器很少重启.我还将缓存过期时间设置为三天 - 数据不会经常更新,并且没有服务最新版本的危险.

我想要做的是按TimerTask设定的时间间隔运行,比方说两天23小时,这将迫使DAO方法从Web服务中提取所有产品数据.然后,该数据将替换缓存中的数据,而不会过期.然后将重置缓存到期计数器 - 数据将在三天后再次到期.这样,控制器方法总是从缓存中获取产品数据,并且页面将是响应的.

我的问题是,如果我使用Spring的缓存抽象,我将如何实现这样的方法?我需要CacheManager直接处理我的方法吗?

另一个问题是:我正确地解决了这个问题吗?有没有更好的方法呢?

Nim*_*sky 7

阻止呼叫,直到缓存可用

@Cacheable(cacheName="yourCache", decoratedCacheType= DecoratedCacheType.SELF_POPULATING_CACHE)
public List<String> getWhatever(int id) {
//call database
}
Run Code Online (Sandbox Code Playgroud)

您可以使用自动刷新缓存而不是timertask:

@Cacheable(cacheName="yourCache", refreshInterval=1000, decoratedCacheType= DecoratedCacheType.REFRESHING_SELF_POPULATING_CACHE)
public List<String> getWhatever(int id) {
  //call database
}
Run Code Online (Sandbox Code Playgroud)

荣誉

  • 只是为了澄清,这是使用ehcache-spring-annotations,而不是spring本身内置的@Cacheable- (2认同)