4

Spring Framework で構築された Java EE アプリケーションでは、DAO で非常にコストのかかる操作を実行する必要があり、これには数分かかる場合があります。Spring MVC を使用して、ユーザーのリクエストがコントローラー メソッドにマップされると、コントローラーを介して 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;
}

この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
}

このアプローチの問題は、キャッシュが空である間、ページに基本的にアクセスできないことです。さらに、キャッシュが空のときに複数のリクエストがページにヒットすると、DAO メソッドが再び起動し、すべてのリクエストが並行して繰り返されます。私が理解している限り、2番目の問題の解決策は a を使用することBlockingCacheですが、まだ実装する機会がありません。

私が望むのは、コントローラ メソッドが常にキャッシュから結果を引き出すようにすることです。@PostConstructすべてのロケールでキャッシュの作成をトリガーするメソッドを実装したいと考えています。何かのようなもの:

@PostConstruct
public void populateCaches() {
    for (Locale locale : localeList) {
        getAllProducts(locale);
    }
}

サーバーが再起動されることはめったにないので、最初の作成に時間がかかることは気にしません。また、キャッシュの有効期限を 3 日間程度に設定します。データは頻繁に更新されず、最新バージョンが提供されなくても危険はありません。

私がやりたいことはTimerTask、設定された間隔で実行することです。たとえば、2 日と 23 時間おきに実行すると、DAO メソッドが Web サービスからすべての製品データを取得するようになります。このデータは、期限切れになることなく、キャッシュ内のデータを置き換えます。その後、キャッシュの有効期限カウンターがリセットされ、データは再び 3 日後に期限切れになります。このようにして、コントローラ メソッドは常にキャッシュから製品データを取得し、ページは応答します。

私の質問は、Spring のキャッシュ抽象化を使用している場合、そのようなメソッドをどのように実装するのでしょうか? CacheManagerメソッドで直接処理する必要がありますか?

もう 1 つの質問は、問題に正しく取り組んでいるかどうかです。これを行うより良い方法はありますか?

4

1 に答える 1

7

キャッシュが利用可能になるまで通話をブロックするには

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

timertask の代わりに、自動更新キャッシュを使用できます。

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

称賛

于 2012-07-06T08:10:50.177 に答える