1. 概要

Spring BootでEhcacheを使用する例を見てみましょう。 JSR-107 キャッシュマネージャーの実装を提供するため、Ehcacheバージョン3を使用します。

この例は、数値の2乗を生成する単純なRESTサービスです。

2. 依存関係

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.6.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.6.1</version></dependency>
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.1</version>
</dependency>     

3. 例

サービスを呼び出して数値を二乗し、結果をJSON文字列として返す単純なRESTコントローラーを作成してみましょう。

@RestController
@RequestMapping("/number", MediaType.APPLICATION_JSON_UTF8_VALUE)
public class NumberController {

    // ...

    @Autowired
    private NumberService numberService;

    @GetMapping(path = "/square/{number}")
    public String getSquare(@PathVariable Long number) {
        log.info("call numberService to square {}", number);
        return String.format("{\"square\": %s}", numberService.square(number));
    }
}

それでは、サービスを作成しましょう。

Springがキャッシングを処理できるように、メソッドに@Cacheableアノテーションを付けます。 このアノテーションの結果として、SpringはNumberServiceのプロキシを作成して、squareメソッドの呼び出しをインターセプトし、Ehcacheを呼び出します。

使用するキャッシュの名前と、オプションでキーを指定する必要があります。 キャッシュされるものを制限する条件を追加することもできます。

@Service
public class NumberService {

    // ...
    @Cacheable(
      value = "squareCache", 
      key = "#number", 
      condition = "#number>10")
    public BigDecimal square(Long number) {
        BigDecimal square = BigDecimal.valueOf(number)
          .multiply(BigDecimal.valueOf(number));
        log.info("square of {} is {}", number, square);
        return square;
    }
}

最後に、メインのSpring Bootアプリケーションを作成しましょう。

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4. キャッシュ構成

Springの@EnableCachingアノテーションをSpringBeanに追加して、Springのアノテーション駆動型キャッシュ管理を有効にする必要があります。

CacheConfigクラスを作成しましょう。

@Configuration
@EnableCaching
public class CacheConfig {
}

Springの自動構成により、EhcacheによるJSR-107の実装が検出されます。 ただし、デフォルトではキャッシュは作成されません。

SpringもEhcacheもデフォルトのehcache.xmlファイルを検索しないためです。 次のプロパティを追加して、Springにその場所を通知します。

spring.cache.jcache.config=classpath:ehcache.xml

squareCache というキャッシュを使用してehcache.xmlファイルを作成しましょう。

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.ehcache.org/v3"
    xmlns:jsr107="http://www.ehcache.org/v3/jsr107"
    xsi:schemaLocation="
            http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
            http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

    <cache alias="squareCache">
        <key-type>java.lang.Long</key-type>
        <value-type>java.math.BigDecimal</value-type>
        <expiry>
            <ttl unit="seconds">30</ttl>
        </expiry>

        <listeners>
            <listener>
                <class>com.baeldung.cachetest.config.CacheEventLogger</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
            </listener>
        </listeners>

        <resources>
            <heap unit="entries">2</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache>

</config>

また、CREATEDEXPIREDの両方のキャッシュイベントをログに記録するキャッシュイベントリスナーを追加しましょう。

public class CacheEventLogger 
  implements CacheEventListener<Object, Object> {

    // ...

    @Override
    public void onEvent(
      CacheEvent<? extends Object, ? extends Object> cacheEvent) {
        log.info(/* message */,
          cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue());
    }
}

5. 動作中

mvn spring-boot:run を実行することで、Mavenを使用してこのアプリを起動できます。

次に、ブラウザを開き、ポート8080でRESTサービスにアクセスします。

http:// localhost:8080 / number / square / 12、に移動すると、 {“ square”:144} に戻り、ログに次のように表示されます。参照してください:

INFO [nio-8080-exec-1] c.b.cachetest.rest.NumberController : call numberService to square 12
INFO [nio-8080-exec-1] c.b.cachetest.service.NumberService : square of 12 is 144
INFO [e [_default_]-0] c.b.cachetest.config.CacheEventLogger : Cache event CREATED for item with key 12. Old value = null, New value = 144

NumberServicesquareメソッドからのログメッセージと、EventLoggerからのCREATEDイベントを確認できます。 次にブラウザを更新すると、ログに追加されたのは次のとおりです。

INFO [nio-8080-exec-2] c.b.cachetest.rest.NumberController : call numberService to square 12

NumberServicesquareメソッドのログメッセージが呼び出されていません。 これは、キャッシュされた値が使用されていることを示しています。

キャッシュされたアイテムの有効期限が切れるのを30秒待ってブラウザを更新すると、EXPIREDイベントとキャッシュに追加された値が表示されます。

INFO [nio-8080-exec-1] (...) NumberController : call numberService to square 12
INFO [e [_default_]-1] (...) CacheEventLogger : Cache event EXPIRED for item with key 12. Old value = 144,New value = null
INFO [nio-8080-exec-1] (... )NumberService : square of 12 is 144
INFO [e [_default_]-1] (...) CacheEventLogger : Cache event CREATED for item with key 12. Old value = null, New value = 144

ブラウザにhttp:// localhost:8080 / number / square / 3 と入力すると、正解は9になりますが、値はキャッシュされません。

これは、 @Cacheable アノテーションで使用した条件が原因で、10より大きい数値の値のみをキャッシュします。

6. 結論

このクイックチュートリアルでは、SpringBootを使用してEhcacheをセットアップする方法を示しました。

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