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 つの質問は、問題に正しく取り組んでいるかどうかです。これを行うより良い方法はありますか?