Introduction à Ehcache

1. Vue d'ensemble

Dans cet article, nous présenterons Ehcache, un cache Java open source largement utilisé. Il comprend des magasins de mémoire et de disque, des écouteurs, des chargeurs de cache, des API RESTful et SOAP et d'autres fonctionnalités très utiles.

Pour montrer comment la mise en cache peut optimiser notre application, nous allons créer une méthode simple qui calculera les valeurs carrées des nombres fournis. À chaque appel, la méthode appelle la méthode CalculateSquareOfNumber (int number) et affiche un message d'information sur la console.

Avec cet exemple simple, nous voulons montrer que le calcul des valeurs au carré n'est effectué qu'une seule fois et que chaque autre appel avec la même valeur d'entrée renvoie le résultat du cache.

Il est important de noter que nous nous concentrons entièrement sur Ehcache lui-même (sans Spring); si vous voulez voir comment Ehcache fonctionne avec Spring, jetez un œil à cet article.

2. Dépendances de Maven

Pour utiliser Ehcache, nous devons ajouter cette dépendance Maven:

 org.ehcache ehcache 3.1.3 

La dernière version de l'artefact Ehcache peut être trouvée ici.

3. Configuration du cache

Ehcache peut être configuré de deux manières:

  • La première consiste à utiliser Java POJO où tous les paramètres de configuration sont configurés via l'API Ehcache
  • La deuxième façon est la configuration via un fichier XML où nous pouvons configurer Ehcache selon la définition de schéma fournie

Dans cet article, nous montrerons les deux approches - Java et configuration XML.

3.1. Configuration Java

Cette sous-section montrera à quel point il est facile de configurer Ehcache avec des POJO. En outre, nous allons créer une classe d'assistance pour une configuration et une disponibilité du cache plus faciles:

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 }

Pour initialiser notre cache, nous devons d'abord définir l' objet Ehcache CacheManager . Dans cet exemple, nous créons un cache par défaut squaredNumber ” avec l' API newCacheManagerBuilder () .

Le cache carte simplement entiers clés entiers valeurs.

Remarquez comment, avant de commencer à utiliser le cache défini, nous devons initialiser l' objet CacheManager avec la méthode init () .

Enfin, pour obtenir notre cache, nous pouvons simplement utiliser l' API getCache () avec les types de nom, de clé et de valeur fournis pour notre cache.

Avec ces quelques lignes, nous avons créé notre premier cache qui est maintenant disponible pour notre application.

3.2. Configuration XML

L'objet de configuration de la sous-section 3.1. équivaut à utiliser cette configuration XML:

 java.lang.Integer java.lang.Integer 10 

Et pour inclure ce cache dans notre application Java, nous devons lire le fichier de configuration XML en Java:

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

4. Test Ehcache

Dans la section 3. nous avons montré comment vous pouvez définir un cache simple pour vos besoins. Pour montrer que la mise en cache fonctionne réellement, nous allons créer la classe SquaredCalculator qui calculera la valeur au carré de l'entrée fournie et stockera la valeur calculée dans un cache.

Bien sûr, si le cache contient déjà une valeur calculée, nous retournerons la valeur mise en cache et éviterons les calculs inutiles:

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; }

Pour compléter notre scénario de test, nous aurons également besoin du code qui calculera les valeurs carrées:

@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"); } }

Si nous exécutons notre test, nous obtiendrons ce résultat dans notre console:

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

Comme vous pouvez le constater, la méthode Calculate () effectuait des calculs uniquement au premier appel. Lors du deuxième appel, toutes les valeurs ont été trouvées dans le cache et renvoyées par celui-ci.

5. Autres options de configuration d'Ehcache

Lorsque nous avons créé notre cache dans l'exemple précédent, il s'agissait d'un simple cache sans aucune option spéciale. Cette section montrera d'autres options utiles pour la création de cache.

5.1. Persistance du disque

S'il y a trop de valeurs à stocker dans le cache, nous pouvons stocker certaines de ces valeurs sur le disque dur.

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();

Instead of default CacheManager, we now use PersistentCacheManager which will persist all values which can't be saved into memory.

From configuration, we can see that cache will save 10 elements into memory and it will allocate 10MB on the hard drive for persistence.

5.2. Data Expiry

If we cache a lot of data, it's natural that we save cached data for some period of time so we can avoid big memory usage.

Ehcache controls data freshness trough Expiry interface:

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

In this cache, all data will live for 60 seconds and after that period of time, it will be deleted from memory.

6. Conclusion

In this article, we showed how to use simple Ehcache caching in a Java application.

Dans notre exemple, nous avons vu que même un cache simplement configuré peut sauver de nombreuses opérations inutiles. De plus, nous avons montré que nous pouvons configurer des caches via POJO et XML et qu'Ehcache a quelques fonctionnalités intéressantes - telles que la persistance et l'expiration des données.

Comme toujours, le code de cet article est disponible sur GitHub.