Exemple de Spring Caching et Ehcache

Exemple de mise en cache de printemps et Ehcache

spring-ehcache

Dans ce didacticiel, nous allons vous montrer comment activer la mise en cache des données dans une application Spring et l'intégrer au frameworkEhcache populaire.

Les outils utilisés

  1. Ehcache 2.9

  2. Spring 4.1.4.RELEASE

  3. Logback 1.0.13

  4. Maven 3 / Gradle 2

  5. JDK 1.7

  6. Eclipse 4.4

Note
Spring prend en charge la mise en cache depuis la version 3.1
Le cache Spring a été considérablement amélioré depuis la version 4.1

1. Structure du répertoire du projet

spring-ehcache-example

2. Dépendances du projet

La mise en cache Spring est dans lesspring-context.jar, pour prendre en charge la mise en cache Ehcache, vous devez également inclure lesspring-context-support.jar.

Pour le projet Maven:

pom.xml

    
        net.sf.ehcache
        ehcache
        2.9.0
    

        
    
        ch.qos.logback
        logback-classic
        1.0.13
    

    
    
        org.springframework
        spring-context
        4.1.4.RELEASE
    

    
    
        org.springframework
        spring-context-support
        4.1.4.RELEASE
    

Pour le projet Gradle:

gradle.build

apply plugin: 'java'
apply plugin: 'eclipse-wtp'

version = '1.0'

// Uses JDK 7
sourceCompatibility = 1.7
targetCompatibility = 1.7

// Get dependencies from Maven central repository
repositories {
    mavenCentral()
}

//Project dependencies
dependencies {
    compile 'org.springframework:spring-context:4.1.4.RELEASE'
    compile 'org.springframework:spring-context-support:4.1.4.RELEASE'
    compile 'net.sf.ehcache:ehcache:2.9.0'
    compile 'ch.qos.logback:logback-classic:1.0.13'
}

3. Exemple Spring sans cache

Un DAO simple pour trouver un film par nom de réalisateur.

Movie.java

package com.example.movie;

import java.io.Serializable;

public class Movie implements Serializable {

    int id;
    String name;
    String directory;

    //getters and setters
    //constructor with fields
    //toString()
}

MovieDao.java

package com.example.movie;

public interface MovieDao{

    Movie findByDirector(String name);

}

MovieDaoImpl.java

package com.example.movie;

import org.springframework.stereotype.Repository;

@Repository("movieDao")
public class MovieDaoImpl implements MovieDao{

    //each call will delay 2 seconds, simulate the slow query call
    public Movie findByDirector(String name) {
        slowQuery(2000L);
        System.out.println("findByDirector is running...");
        return new Movie(1,"Forrest Gump","Robert Zemeckis");
    }

    private void slowQuery(long seconds){
        try {
                Thread.sleep(seconds);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
    }

}

AppConfig.java

package com.example.test;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({ "com.example.*" })
public class AppConfig {
}

App.java

package com.example.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.example.movie.MovieDao;

public class App {

    private static final Logger log = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MovieDao obj = (MovieDao) context.getBean("movieDao");

        log.debug("Result : {}", obj.findByDirector("dummy"));
        log.debug("Result : {}", obj.findByDirector("dummy"));
        log.debug("Result : {}", obj.findByDirector("dummy"));

    }
}

Sortie

findByDirector is running...
2015-01-22 10:39:04 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
findByDirector is running...
2015-01-22 10:39:06 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
findByDirector is running...
2015-01-22 10:39:08 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]

Chaque appel àfindByDirector prendra 2 secondes de retard.

4. Exemple de mise en cache de printemps + EhCache

Maintenant, nous allons activer la mise en cache des données sur la méthodefindByDirector.

4.1 Create a ehcache.xml file, to tell Ehcache how and where to cache the data.

src/main/resource/ehcache.xml



    

    
        
    

Note
Pour savoir comment configurer Ehcache, lisez cet exemple officiel deehcache.xml.

4.2 Add @Cacheable on the method you want to cache.

MovieDaoImpl.java

package com.example.movie;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;

@Repository("movieDao")
public class MovieDaoImpl implements MovieDao{

    //This "movieFindCache" is delcares in ehcache.xml
    @Cacheable(value="movieFindCache", key="#name")
    public Movie findByDirector(String name) {
        slowQuery(2000L);
        System.out.println("findByDirector is running...");
        return new Movie(1,"Forrest Gump","Robert Zemeckis");
    }

    private void slowQuery(long seconds){
        try {
                Thread.sleep(seconds);
            } catch (InterruptedException e) {
                throw new IllegalStateException(e);
            }
    }

}

4.3 Enable Caching with @EnableCaching and declared a EhCacheCacheManager.

AppConfig.java

package com.example.test;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
@EnableCaching
@ComponentScan({ "com.example.*" })
public class AppConfig {

    @Bean
    public CacheManager cacheManager() {
        return new EhCacheCacheManager(ehCacheCacheManager().getObject());
    }

    @Bean
    public EhCacheManagerFactoryBean ehCacheCacheManager() {
        EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
        cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
        cmfb.setShared(true);
        return cmfb;
    }
}

4.4 In non-web application, you need to shut down the Spring context manually, so that Ehcache got chance to shut down as well, otherwise Ehcache manager will hang there.

App.java

package com.example.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.example.movie.MovieDao;

public class App {

    private static final Logger log = LoggerFactory.getLogger(App.class);

    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MovieDao obj = (MovieDao) context.getBean("movieDao");

        log.debug("Result : {}", obj.findByDirector("dummy"));
        log.debug("Result : {}", obj.findByDirector("dummy"));
        log.debug("Result : {}", obj.findByDirector("dummy"));

        //shut down the Spring context.
        ((ConfigurableApplicationContext)context).close();

    }
}

Sortie

INFO: Initializing EhCache CacheManager

findByDirector is running...
2015-01-22 10:53:28 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
2015-01-22 10:53:28 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]
2015-01-22 10:53:28 [main] DEBUG com.example.test.App - Result : Movie [id=1, name=Forrest Gump, directory=Robert Zemeckis]

INFO: Shutting down EhCache CacheManager

Passez en revue le temps exécuté, il n'y a pas de retard. De plus, un seul «findByDirector est en cours d'exécution…» est imprimé, car cette méthode n'est exécutée qu'une seule fois, l'appel suivant récupérera l'objet du cache.

Terminé.

More on Spring Caching
Cet article est pour vous aider à démarrer avec la mise en cache des données Spring, pour en savoir plus sur d'autres annotations de mise en cache comme@CacheEvict,@CachePut,@CacheConfig et etc. , veuillez vous référer à ceSpring Cache Abstraction documentation officiel, assez détaillé là-bas.

Télécharger le code source

Téléchargez-le -Spring-Ehcache-Example.zip (20 Ko)