Введение в Ehcache

Введение в Ehcache

1. обзор

В этой статье мы познакомимся сEhcache, широко используемым кэшем на основе Java с открытым исходным кодом. Он включает в себя хранилища памяти и диска, прослушиватели, загрузчики кеша, API-интерфейсы RESTful и SOAP и другие очень полезные функции.

Чтобы показать, как кэширование может оптимизировать наше приложение, мы создадим простой метод, который будет вычислять квадратные значения предоставленных чисел. При каждом вызове метод будет вызывать методcalculateSquareOfNumber(int number) и выводить информационное сообщение на консоль.

В этом простом примере мы хотим показать, что вычисление квадратов значений выполняется только один раз, и каждый второй вызов с тем же входным значением возвращает результат из кэша.

Важно отметить, что мы полностью сосредоточены на самом Ehcache (без Spring); если вы хотите увидеть, как Ehcache работает со Spring, взгляните на readthis article.

2. Maven Зависимости

Чтобы использовать Ehcache, нам нужно добавить эту зависимость Maven:


    org.ehcache
    ehcache
    3.1.3

Последнюю версию артефакта Ehcache можно найтиhere.

3. Конфигурация кэша

Ehcache можно настроить двумя способами:

  • Первый способ - через Java POJO, где все параметры конфигурации настраиваются через Ehcache API.

  • Второй способ - это конфигурация через XML-файл, где мы можем настроить Ehcache в соответствии сprovided schema definition.

В этой статье мы покажем оба подхода - конфигурацию Java и XML.

3.1. Конфигурация Java

Этот подраздел покажет, как легко настроить Ehcache с POJO. Также мы создадим вспомогательный класс для упрощения настройки и доступности кэша:

public class CacheHelper {

    private CacheManager cacheManager;
    private Cache squareNumberCache;

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

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

    public Cache getSquareNumberCacheFromCacheManager() {
        return cacheManager.getCache("squaredNumber", Integer.class, Integer.class);
    }

    // standard getters and setters
}

Чтобы инициализировать наш кеш, сначала нам нужно определить объект EhcacheCacheManager. В этом примере мы создаем кеш по умолчаниюsquaredNumber” с APInewCacheManagerBuilder().

Кеш просто отображает ключиInteger в значенияInteger.

Обратите внимание, что перед тем, как мы начнем использовать определенный кеш, нам нужно инициализировать объектCacheManager с помощью методаinit().

Наконец, чтобы получить наш кеш, мы можем просто использовать APIgetCache() с предоставленными типами имени, ключа и значения нашего кеша.

С помощью этих нескольких строк мы создали наш первый кеш, который теперь доступен для нашего приложения.

3.2. Конфигурация XML

Конфигурация объекта из подраздела 3.1. равнозначно использованию этой конфигурации XML:


    java.lang.Integer
    java.lang.Integer
    10

И чтобы включить этот кеш в наше Java-приложение, нам нужно прочитать XML-файл конфигурации на Java:

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

4. Тест Ehcache

В разделе 3. мы показали, как вы можете определить простой кеш для ваших целей. Чтобы показать, что кеширование действительно работает, мы создадим класс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() выполнял вычисления только при первом вызове. При втором вызове все значения были найдены в кеше и возвращены из него.

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 элементов в памяти и выделит 10 МБ на жестком диске для сохранения.

5.2. Срок действия данных

Если мы кэшируем много данных, естественно, что мы сохраняем кешированные данные в течение некоторого периода времени, чтобы избежать большого использования памяти.

Ehcache контролирует актуальность данных через интерфейсExpiry:

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

В этом кэше все данные будут жить в течение 60 секунд, и по истечении этого периода они будут удалены из памяти.

6. Заключение

В этой статье мы показали, как использовать простое кэширование Ehcache в приложении Java.

В нашем примере мы увидели, что даже просто настроенный кеш может сохранить множество ненужных операций. Кроме того, мы показали, что мы можем настраивать кеши с помощью POJO и XML и что Ehcache обладает довольно хорошими функциями, такими как постоянство и истечение срока действия данных.

Как всегда, код из этой статьи можно найтиon GitHub.