springboot integration ehcache implementation of caching mechanism

  • 2021-01-14 05:55:24
  • OfStack

EhCache is a pure Java in-process caching framework. It is fast, clean, and is the default CacheProvider in Hibernate.

ehcache provides a variety of caching strategies, mainly at the memory and disk levels, so there is no need to worry about capacity.

spring-boot is a fast integration framework designed to simplify the initial setup and development process for new Spring applications. The framework uses a specific way to configure, eliminating the need for developers to define boilerplate configurations.

Because spring-boot does not require any boilerplate configuration files, spring-boot will be slightly different when integrated with some other frameworks.

1.spring-boot is a framework for jar packages managed by maven. The dependencies required to integrate ehcache are as follows


 <dependency>
  <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
     <groupId>net.sf.ehcache</groupId>
   <artifactId>ehcache</artifactId>
     <version>2.8.3</version>
</dependency> 

Specific pom.xml documents are as follows


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lclc.boot</groupId>
  <artifactId>boot-cache</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <!-- Inherit defaults from Spring Boot -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.1.3.RELEASE</version>
  </parent>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>17.0</version>
    </dependency>
    
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
    </dependency>
    <dependency>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>ehcache</artifactId>
      <version>2.8.3</version>
    </dependency>
  </dependencies>

  <dependencyManagement>
    <dependencies>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

  <repositories>
    <repository>
      <id>spring-snapshots</id>
      <url>http://repo.spring.io/snapshot</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>spring-milestones</id>
      <url>http://repo.spring.io/milestone</url>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <id>spring-snapshots</id>
      <url>http://repo.spring.io/snapshot</url>
    </pluginRepository>
    <pluginRepository>
      <id>spring-milestones</id>
      <url>http://repo.spring.io/milestone</url>
    </pluginRepository>
  </pluginRepositories>
</project>

2. To use ES34en, we need an ES35en. ES36en to define some properties of ES37en.


<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
 updateCheck="false">
     <diskStore path="java.io.tmpdir/Tmp_EhCache" />
      <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU" />

      <cache name="demo" eternal="false" maxElementsInMemory="100" overflowToDisk="false" diskPersistent="false"
  timeToIdleSeconds="0" timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU" />

</ehcache>

Explain the tags in the xml file.

(1).diskStore: is the cache path, ehcache is divided into memory and disk levels, this property defines the cache location of disk. The parameters are explained as follows:

user. home � user home directory user. dir � user the current working directory java. io. tmpdir � default temporary file path

(2).defaultCache: Default caching policy, which is used when ehcache cannot find a defined cache. You can only define one.

(3). ES59en: Custom cache policy, which is a custom cache policy. The parameters are explained as follows:

The properties of the cache element: name: Cache name maxElementsInMemory: Maximum number of cache objects in memory maxElementsOnDisk: Maximum number of cache objects in hard disk. 0 means infinity eternal: true means that the object is never expired. The timeToIdleSeconds and timeToLiveSeconds properties are ignored, and the default is false overflowToDisk: true means that when the number of objects in memory cache reaches the limit of maxElementsInMemory, the overflow objects will be written to the hard disk cache. Note: If the cached object is to be written to disk, it must implement the ES73en interface. diskSpoolBufferSizeMB: Disk cache size, default is 30MB. Each ES76en should have its own 1 cache. diskPersistent: Whether to cache virtual machine restart data diskExpiryThreadIntervalSeconds: Disk failure thread runtime interval, default is 120 seconds timeToIdleSeconds: Sets the maximum time, in seconds, that an object is allowed to remain idle. If an object has been idle for longer than the value of the timeToIdleSeconds property since the last time it was accessed, the object will expire and EHCache will clear it from the cache. The eternal attribute is only valid if the eternal attribute is false. If this property has a value of 0, then the object can be idle indefinitely timeToLiveSeconds: Sets the maximum time, in seconds, that an object is allowed to exist in the cache. If an object has been in the cache for longer than the value of the timeToLiveSeconds property since it was stored, the object will expire and EHCache will remove it from the cache. The eternal attribute is valid only if the eternal attribute is false. If this property has a value of 0, the object can remain in the cache indefinitely. timeToLiveSeconds must be greater than the timeToIdleSeconds attribute for it to be meaningful memoryStoreEvictionPolicy: When the maxElementsInMemory limit is reached, Ehcache will clean memory according to the specified policy. The optional policies are: LRU (least recently used, default policy), FIFO (first in, first out), LFU (minimum number of visits).

SpringBoot supports many kinds of caching: redis, guava, ehcahe, jcache, and more.

redis and ehcache are different:

Redis: This is a separate running program that needs to be installed separately and operated using Jedis in Java. Because it's independent, so if you write a unit test program, put some data in Redis, and then write another program to get the data, you can get the data. .
ehcache: It is significantly different from Redis in that it is tied to the java program. The java program lives as long as it lives. For example, write an independent program to put the data, and then write an independent program to take the data, then you can not get the data. You can only get the data in a standalone program.

3. Expose ehcache's manager to spring's context container.


@Configuration
//  The annotation initiates the cache 
@EnableCaching
public class CacheConfiguration {

  /*
   * ehcache  The main manager 
   */
  @Bean(name = "appEhCacheCacheManager")
  public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){
    return new EhCacheCacheManager (bean.getObject ());
  }

  /*
   *  According to the shared Settings for whether or not ,Spring Respectively by CacheManager.create() or new CacheManager() Method to create 1 a ehcache base .
   */
  @Bean
  public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){
    EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean ();
    cacheManagerFactoryBean.setConfigLocation (new ClassPathResource ("conf/ehcache-app.xml"));
    cacheManagerFactoryBean.setShared (true);
    return cacheManagerFactoryBean;
  }
}

Configuration: annotated for spring-boot, mainly marked as a configuration class, preferred to scan.

Bean: Add bean to spring container.

With all the configuration now in place, integrating the framework via spring-boot is as simple as that.

4. Use ehcache

Using ehcache mainly uses the spring caching mechanism. We implemented the spring caching mechanism above using ehcache, so we will use the spring caching mechanism completely when using aspects.

There are several specific annotations involved:

@Cacheable: is responsible for adding the method's return value to the cache, parameter 3
@CacheEvict: Responsible for clearing the cache, parameter 4

Parameter explanation:

value: Cache location name, cannot be empty, if using EHCache, it is name of cache declared in ehcache. xml key: The cached key is null by default, which means that the method parameter type and parameter value are used as key, and SpEL is supported condition: trigger condition, only meet the condition will be added to the cache, the default is empty, both means that all join the cache, support SpEL allEntries: CacheEvict parameter, true means to clear all cache in value, the default is false

Without further ado, go straight to the code:


@Service
public class CacheDemoServiceImpl implements CacheDemoService {
  /**
   *  The cache key
   */
  public static final String THING_ALL_KEY  = "\"thing_all\"";
  /**
   * value Property indicates which cache policy to use, and the cache policy at ehcache.xml
   */
  public static final String DEMO_CACHE_NAME = "demo";  
  @CacheEvict(value = DEMO_CACHE_NAME,key = THING_ALL_KEY)
  @Override
  public void create(Thing thing){
    Long id = getNextId ();
    thing.setId (id);
    data.put (id, thing);
  } 
   
   @Cacheable(value = DEMO_CACHE_NAME,key = "#thing.getId()+'thing'")
  @Override
  public Thing findById(Long id){
    System.err.println (" No cache gone! " + id);
    return data.get (id);
  }

  @Cacheable(value = DEMO_CACHE_NAME,key = THING_ALL_KEY)
  @Override
  public List<Thing> findAll(){
    return Lists.newArrayList (data.values ());
  }
   
  @Override
  @CachePut(value = DEMO_CACHE_NAME,key = "#thing.getId()+'thing'")
  @CacheEvict(value = DEMO_CACHE_NAME,key = THING_ALL_KEY)
  public Thing update(Thing thing){
    System.out.println (thing);
    data.put (thing.getId (), thing);
    return thing;
  }

  @CacheEvict(value = DEMO_CACHE_NAME)
  @Override
  public void delete(Long id){
    data.remove (id);
  }  
}

5. Just annotate service layer methods with annotations to use the cache, save the cache on find**, clear the cache on delete**, and update**.

Cache annotated in detail

CacheConfig: This is mainly used to configure some common cache configuration that will be used in this class. Here @CacheConfig (cacheNames = "users") : The content returned from the configured data access object will be stored in a cache object named users, or we can skip this annotation and define it directly by the name of @Cacheable's own configured cache set.

Cacheable: The return value of the configured findByName function will be added to the cache. At the same time, during the query, it will first get from the cache, and only initiate the access to the database if it does not exist. The annotation mainly has the following parameters:

value, cacheNames: Two identical parameters (cacheNames is new to Spring 4 and is used as an alias for value) to specify the collection name of the cache store. With the addition of @CacheConfig in Spring 4, the value attribute, which was required in Spring 3, is now not required SpEL: The cached key value stored in the Map collection is not required. By default, it is the key value as a combination of all the parameters of the function. For example, @Cacheable(key = "#p0") : uses the first argument of the function as the cached key value condition: This is a condition for the object to be cached. It is not necessary to use the SpEL expression. Only contents that meet the expression condition will be cached, for example: @Cacheable(key = "#p0", condition = "#p0.length() < 3"), which means that the first parameter will be cached only if the length of the first parameter is less than 3. If this configuration is done, the user AAA above will not be cached. unless: Another cache condition parameter, not required, using an SpEL expression. Where it differs from the condition argument is in its timing. This condition is judged after the function has been called, so it can be judged by result. keyGenerator: Used to specify the key generator, not required. If you need to specify a custom key generator, we need to implement org. springframework. cache. interceptor. KeyGenerator interface, and use this parameter to specify. Note that this parameter and key are mutually exclusive cacheManager: Used to specify which cache manager to use, not required. It is only needed if there are more than one cacheResolver: Used to specify which cache parser to use, not required. By org. springframework. cache. interceptor. CacheResolver interface to implement their own caching parser, and the parameters are specified.

In addition to the two annotations used here, there are the following core annotations:

@CachePut: is configured on a function and can define conditions for caching based on parameters. Unlike @Cacheable, it actually calls the function every time, so it is mainly used for data addition and modification operations. Its parameters are similar to @Cacheable. For specific functions, please refer to the parsing of @Cacheable parameters above

CacheEvict: Configurated on functions, usually used on delete methods, to remove data from the cache. In addition to the arguments like @Cacheable1, it has the following two arguments:

allEntries: Not required. Default is false. When true is used, all data is removed beforeInvocation: Not required, the default is false, which removes the data after the method is called. When it is true, the data is removed before the method is called.

Related articles: