1. 概要

この記事では、広く使用されているオープンソースのJavaベースのキャッシュであるEhcacheを紹介します。 これは、メモリとディスクストア、リスナー、キャッシュローダー、RESTfulおよびSOAP API、およびその他の非常に便利な機能を備えています。

キャッシングがアプリケーションを最適化する方法を示すために、提供された数値の2乗値を計算する簡単なメソッドを作成します。 呼び出しごとに、メソッドはcalculateSquareOfNumber(int number)メソッドを呼び出し、コンソールに情報メッセージを出力します。

この簡単な例では、2乗値の計算が一度だけ行われ、同じ入力値を持つ他のすべての呼び出しがキャッシュから結果を返すことを示したいと思います。

(Springなしで)Ehcache自体に完全に焦点を合わせていることに注意することが重要です。 EhcacheがSpringでどのように機能するかを知りたい場合は、この記事をお読みください。

2. Mavenの依存関係

Ehcacheを使用するには、次のMaven依存関係を追加する必要があります。

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.1.3</version>
</dependency>

Ehcacheアーティファクトの最新バージョンはここにあります。

3. キャッシュ構成

Ehcacheは、次の2つの方法で構成できます。

  • 最初の方法は、すべての構成パラメーターがEhcacheAPIを介して構成されるJavaPOJOを使用する方法です。
  • 2番目の方法は、提供されたスキーマ定義に従ってEhcacheを構成できるXMLファイルによる構成です。

この記事では、JavaとXML構成の両方のアプローチを紹介します。

3.1. Java構成

このサブセクションでは、POJOを使用してEhcacheを構成するのがいかに簡単かを示します。 また、キャッシュの構成と可用性を容易にするためのヘルパークラスを作成します。

public class CacheHelper {

    private CacheManager cacheManager;
    private Cache<Integer, Integer> squareNumberCache;

    public CacheHelper() {
        cacheManager = CacheManagerBuilder
          .newCacheManagerBuilder().build();
        cacheManager.init();

        squareNumberCache = cacheManager
          .createCache("squaredNumber", CacheConfigurationBuilder
            .newCacheConfigurationBuilder(
              Integer.class, Integer.class,
              ResourcePoolsBuilder.heap(10)));
    }

    public Cache<Integer, Integer> getSquareNumberCacheFromCacheManager() {
        return cacheManager.getCache("squaredNumber", Integer.class, Integer.class);
    }
    
    // standard getters and setters
}

キャッシュを初期化するには、まず、Ehcache CacheManagerオブジェクトを定義する必要があります。 この例では、 newCacheManagerBuilder()APIを使用してデフォルトのcachesquaredNumber”を作成しています。

キャッシュは、IntegerキーをInteger値にマップするだけです。

定義されたキャッシュの使用を開始する前に、 CacheManagerオブジェクトをinit()メソッドで初期化する必要があることに注意してください。

最後に、キャッシュを取得するには、 getCache() APIを使用して、キャッシュの名前、キー、および値のタイプを指定します。

これらの数行で、アプリケーションで使用できる最初のキャッシュを作成しました。

3.2. XML構成

サブセクション3.1の構成オブジェクト。 このXML構成を使用するのと同じです。

<cache-template name="squaredNumber">
    <key-type>java.lang.Integer</key-type>
    <value-type>java.lang.Integer</value-type>
    <heap unit="entries">10</heap>
</cache-template>

そして、このキャッシュをJavaアプリケーションに含めるには、JavaでXML構成ファイルを読み取る必要があります。

URL myUrl = getClass().getResource(xmlFile); 
XmlConfiguration xmlConfig = new XmlConfiguration(myUrl); 
CacheManager myCacheManager = CacheManagerBuilder
  .newCacheManager(xmlConfig);

4. Ehcacheテスト

セクション3。 目的に合わせて単純なキャッシュを定義する方法を示しました。 キャッシュが実際に機能することを示すために、提供された入力の2乗値を計算し、計算された値をキャッシュに格納するSquaredCalculatorクラスを作成します。

もちろん、キャッシュにすでに計算値が含まれている場合は、キャッシュされた値を返し、不要な計算を回避します。

public class SquaredCalculator {
    private CacheHelper cache;

    public int getSquareValueOfNumber(int input) {
        if (cache.getSquareNumberCache().containsKey(input)) {
            return cache.getSquareNumberCache().get(input);
        }

        System.out.println("Calculating square value of " + input + 
          " and caching result.");

        int squaredValue = (int) Math.pow(input, 2);
        cache.getSquareNumberCache().put(input, squaredValue);

        return squaredValue;
    }

    //standard getters and setters;
}

テストシナリオを完了するには、正方形の値を計算するコードも必要です。

@Test
public void whenCalculatingSquareValueAgain_thenCacheHasAllValues() {
    for (int i = 10; i < 15; i++) {
        assertFalse(cacheHelper.getSquareNumberCache().containsKey(i));
        System.out.println("Square value of " + i + " is: "
          + squaredCalculator.getSquareValueOfNumber(i) + "\n");
    }      
    
    for (int i = 10; i < 15; i++) {
        assertTrue(cacheHelper.getSquareNumberCache().containsKey(i));
        System.out.println("Square value of " + i + " is: "
          + squaredCalculator.getSquareValueOfNumber(i) + "\n");
    }
}

テストを実行すると、コンソールに次の結果が表示されます。

Calculating square value of 10 and caching result.
Square value of 10 is: 100

Calculating square value of 11 and caching result.
Square value of 11 is: 121

Calculating square value of 12 and caching result.
Square value of 12 is: 144

Calculating square value of 13 and caching result.
Square value of 13 is: 169

Calculating square value of 14 and caching result.
Square value of 14 is: 196

Square value of 10 is: 100
Square value of 11 is: 121
Square value of 12 is: 144
Square value of 13 is: 169
Square value of 14 is: 196

お気づきのように、calculate()メソッドは最初の呼び出しでのみ計算を行っていました。 2回目の呼び出しで、すべての値がキャッシュで検出され、キャッシュから返されました。

5. その他のEhcache構成オプション

前の例でキャッシュを作成したとき、それは特別なオプションのない単純なキャッシュでした。 このセクションでは、キャッシュの作成に役立つ他のオプションを示します。

5.1. ディスクの永続性

キャッシュに保存するには値が多すぎる場合は、それらの値の一部をハードドライブに保存できます。

PersistentCacheManager persistentCacheManager = 
  CacheManagerBuilder.newCacheManagerBuilder()
    .with(CacheManagerBuilder.persistence(getStoragePath()
      + File.separator 
      + "squaredValue")) 
    .withCache("persistent-cache", CacheConfigurationBuilder
      .newCacheConfigurationBuilder(Integer.class, Integer.class,
        ResourcePoolsBuilder.newResourcePoolsBuilder()
          .heap(10, EntryUnit.ENTRIES)
          .disk(10, MemoryUnit.MB, true)) 
      )
  .build(true);

persistentCacheManager.close();

デフォルトのCacheManagerの代わりに、 PersistentCacheManager を使用するようになりました。これにより、メモリに保存できないすべての値が永続化されます。

構成から、キャッシュが10個の要素をメモリに保存し、永続性のためにハードドライブに10MBを割り当てることがわかります。

5.2. データの有効期限

大量のデータをキャッシュする場合、大量のメモリ使用を回避できるように、キャッシュされたデータを一定期間保存するのは当然です。

Ehcacheは、Expiryインターフェースを介してデータの鮮度を制御します。

CacheConfiguration<Integer, Integer> cacheConfiguration 
  = CacheConfigurationBuilder
    .newCacheConfigurationBuilder(Integer.class, Integer.class, 
      ResourcePoolsBuilder.heap(100)) 
    .withExpiry(Expirations.timeToLiveExpiration(Duration.of(60, 
      TimeUnit.SECONDS))).build();

このキャッシュでは、すべてのデータが60秒間存続し、その期間が経過すると、メモリから削除されます。

6. 結論

この記事では、Javaアプリケーションで単純なEhcacheキャッシングを使用する方法を示しました。

この例では、単純に構成されたキャッシュでさえ、多くの不要な操作を節約できることがわかりました。 また、POJOとXMLを介してキャッシュを構成できること、およびEhcacheには永続性やデータの有効期限などの優れた機能があることを示しました。

いつものように、この記事のコードはGitHubにあります。