§PlayキャッシュAPI
データのキャッシュは、最新のアプリケーションでは典型的な最適化であり、Playはグローバルキャッシュを提供します。
注意: キャッシュに関する重要な点は、キャッシュのように動作することです。保存したデータが失われる可能性があります。
キャッシュに保存されているデータについては、データが失われた場合に備えて、再生成戦略を導入する必要があります。この哲学はPlayの基礎の1つであり、セッションがその存続期間中ずっと値を保持することが期待されるJava EEとは異なります。
Playは、Caffeineに基づくCacheApi実装と、Ehcache 2.xに基づくレガシー実装を提供します。インプロセスキャッシングの場合、Caffeineが通常は最適な選択肢です。分散キャッシングが必要な場合は、memcachedとredis用のサードパーティプラグインがあります。
§キャッシュAPIのインポート
Playは、キャッシュAPIとCaffeineおよびEhcache実装用に個別の依存関係を提供します。
§Caffeine
Caffeine実装を取得するには、依存関係リストに`caffeine`を追加します
libraryDependencies ++= Seq(
caffeine
)
これにより、実行時DIのバインディングも自動的に設定され、コンポーネントを注入できるようになります。
§EhCache
EhCache実装を取得するには、依存関係リストに`ehcache`を追加します
libraryDependencies ++= Seq(
ehcache
)
これにより、実行時DIのバインディングも自動的に設定され、コンポーネントを注入できるようになります。
§カスタムキャッシュ実装
APIのみを追加するには、依存関係リストに`cacheApi`を追加します。
libraryDependencies ++= Seq(
cacheApi
)
APIの依存関係は、特定のキャッシュ実装に依存することなく、`Cached`ヘルパーと`AsyncCacheApi`などに独自の バインディングを定義する場合に役立ちます。カスタムキャッシュモジュールを作成している場合は、これを使用する必要があります。
§キャッシュAPIへのアクセス
キャッシュAPIは、非同期実装と同期実装のどちらが必要かによって、AsyncCacheApiインターフェースとSyncCacheApiインターフェースによって定義され、他の依存関係と同様にコンポーネントに注入できます。例:
import javax.inject.Inject;
import play.cache.*;
import play.mvc.*;
public class Application extends Controller {
private AsyncCacheApi cache;
@Inject
public Application(AsyncCacheApi cache) {
this.cache = cache;
}
// ...
}
**注意:** APIは、さまざまな実装をプラグインできるように意図的に最小限に抑えられています。より具体的なAPIが必要な場合は、キャッシュライブラリによって提供されるAPIを使用してください。
このシンプルなAPIを使用して、キャッシュにデータを保存できます
CompletionStage<Done> result = cache.set("item.key", frontPageNews);
必要に応じて、キャッシュの有効期限(秒単位)を指定できます
// Cache for 15 minutes
CompletionStage<Done> result = cache.set("item.key", frontPageNews, 60 * 15);
後でデータを取得できます
CompletionStage<Optional<News>> news = cache.get("item.key");
キャッシュに値が見つからない場合に値を生成して保存する`Callable`を提供することもできます
CompletionStage<News> maybeCached =
cache.getOrElseUpdate("item.key", this::lookUpFrontPageNews);
**注意**: `getOrElseUpdate`はEhCacheではアトミック操作ではなく、`get`を実行した後に`Callable`から値を計算し、次に`set`を実行することで実装されます。これは、複数のスレッドが同時に`getOrElse`を呼び出している場合、値が複数回計算される可能性があることを意味します。
キャッシュからアイテムを削除するには、`remove`メソッドを使用します
CompletionStage<Done> result = cache.remove("item.key");
キャッシュからすべてのアイテムを削除するには、`removeAll`メソッドを使用します
CompletionStage<Done> resultAll = cache.removeAll();
`removeAll()`は`AsyncCacheApi`でのみ使用できます。キャッシュのすべての要素を削除することは、同期的に行うことはめったにないためです。キャッシュからすべてのアイテムを削除することは、アプリの通常の操作の一部ではなく、特別な場合の管理操作としてのみ必要になることが想定されています。
SyncCacheApiは、Futureを使用する代わりに値を直接返すことを除いて、同じAPIを持っていることに注意してください。
§異なるキャッシュへのアクセス
名前で異なる設定を持つ異なるキャッシュを定義して使用することが可能です。異なるキャッシュにアクセスするには、それらを注入するときに、依存関係にNamedCache修飾子を使用します。例:
import javax.inject.Inject;
import play.cache.*;
import play.mvc.*;
public class Application extends Controller {
@Inject
@NamedCache("session-cache")
SyncCacheApi cache;
// ...
}
複数の異なるキャッシュにアクセスする場合は、`application.conf`でPlayにそれらをバインドするように指示する必要があります。次のようにします。
play.cache.bindCaches = ["db-cache", "user-cache", "session-cache"]
名前付きキャッシュの定義と設定は、使用しているキャッシュ実装によって異なります。Caffeineを使用した名前付きキャッシュの設定例を以下に示します。
§Caffeineを使用した名前付きキャッシュの設定
すべてのキャッシュのフォールバックとして使用されるデフォルトのカスタム設定を渡す場合は、次のように指定することで実行できます
play.cache.caffeine.defaults = {
initial-capacity = 200
...
}
特定のキャッシュのカスタム設定データを渡すこともできます。次のようにします。
play.cache.caffeine.user-cache = {
initial-capacity = 200
...
}
§EhCacheを使用した名前付きキャッシュの設定
EhCache実装では、デフォルトのキャッシュはplayと呼ばれ、ehcache.xmlというファイルを作成することで設定できます。追加のキャッシュは、異なる設定、または実装で設定できます。
デフォルトでは、Playは`play.cache.bindCaches`から名前を持つキャッシュを作成しようとします。`ehcache.xml`で自分で定義したい場合は、次のように設定できます
play.cache.createBoundCaches = false
§実行コンテキストの設定
デフォルトでは、CaffeineとEhCacheは要素をメモリに保存します。そのため、ブロッキングI/Oがほとんどないため、キャッシュの読み取りと書き込みは非常に高速です。
ただし、キャッシュの設定方法によっては(たとえば、EhCacheの`DiskStore`を使用するなど)、ブロッキングI/Oが発生する可能性があり、非同期実装でもデフォルトの実行コンテキストでスレッドをブロックするため、コストがかかりすぎる可能性があります。
そのような場合は、異なるPekkoディスパッチャーを設定し、`play.cache.dispatcher`を介して設定して、キャッシュプラグインがそれを使用するようにできます
play.cache.dispatcher = "contexts.blockingCacheDispatcher"
contexts {
blockingCacheDispatcher {
fork-join-executor {
parallelism-factor = 3.0
}
}
}
§Caffeine
Caffeineを使用する場合、これはCaffeineの内部エグゼキューターを設定します。 実際には、`play.cache.dispatcher`を設定すると、`play.cache.caffeine.defaults.executor`が設定されます。上記で説明したように、異なるキャッシュに異なるエグゼキューターを設定できます
play.cache.caffeine.user-cache = {
executor = "contexts.anotherBlockingCacheDispatcher"
...
}
§EhCache
EhCacheの場合、Playは指定されたディスパッチャーのスレッドでFuture内のEhCache操作を実行します。
§HTTPレスポンスのキャッシュ
標準の`Action`コンポジションを使用して、スマートキャッシュアクションを簡単に作成できます。
**ヒント:** Play HTTP `Result`インスタンスは、キャッシュして後で再利用しても安全です。
Playは、標準ケース用のデフォルトの組み込みヘルパーを提供します
@Cached(key = "homePage")
public Result index() {
return ok("Hello world");
}
§カスタム実装
キャッシュAPIのカスタム実装を提供することが可能です。 `cacheApi`依存関係があることを確認してください。
その後、AsyncCacheApi を実装し、DIコンテナにバインドすることができます。また、SyncCacheApi を DefaultSyncCacheApi にバインドすることもできます。これは、非同期実装を単純にラップしたものです。
キャッシュの実装によっては、removeAll
メソッドがサポートされていない場合があります。これは、不可能であるか、または不必要に非効率的であるためです。その場合は、removeAll
メソッドで UnsupportedOperationException
をスローすることができます。
デフォルト実装に加えてキャッシュAPIの実装を提供するには、カスタム修飾子を作成するか、NamedCache
修飾子を再利用して実装をバインドすることができます。
§カスタム実装とCaffeineを併用する
Caffeineのデフォルト実装を使用するには、caffeine
依存関係が必要であり、application.conf
でCaffeineモジュールが自動的にバインドされないように無効にする必要があります。
play.modules.disabled += "play.api.cache.caffeine.CaffeineCacheModule"
§カスタム実装とEhCacheを併用する
EhCacheのデフォルト実装を使用するには、ehcache
依存関係が必要であり、application.conf
でEhCacheモジュールが自動的にバインドされないように無効にする必要があります。
play.modules.disabled += "play.api.cache.ehcache.EhCacheModule"
このドキュメントに誤りを見つけましたか? このページのソースコードはこちらにあります。ドキュメントガイドラインをお読みいただいた後、プルリクエストを送信してください。質問やアドバイスがあれば、コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。