Spring Boot integrates Ehcache cache, which is done in three steps!

This content mainly introduces the data caching function of Spring Boot application based on Ehcache 3.0. In the Spring Boot application, we can use Spring Caching to quickly handle data caching.

Next we'll show you how to do Spring Boot caching in three steps.

1. Create a Spring Boot project

The maven dependency file of the Spring Boot application you create should at least look like this:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ramostear</groupId>
    <artifactId>cache</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>cache</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

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

</project>

Dependency description:

  • Spring Boot starter cache provides caching support for Spring Boot applications
  • Ehcache provides the cache implementation of ehcache
  • Cache API provides the cache specification based on JSR-107

2. Configure Ehcache cache

Now, you need to tell Spring Boot where to find the cache configuration file, which needs to be set in the Spring Boot configuration file:

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

Then use the @ EnableCaching annotation to enable the Spring Boot application caching function. You can operate in the application main class:

package com.ramostear.cache;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class CacheApplication {

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

Next, you need to create an ehcache configuration file, which is placed in the classpath, such as the resources directory:

<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">
    <service>
        <jsr107:defaults enable-statistics="true"/>
    </service>

    <cache alias="person">
        <key-type>java.lang.Long</key-type>
        <value-type>com.ramostear.cache.entity.Person</value-type>
        <expiry>
            <ttl unit="minutes">1</ttl>
        </expiry>
        <listeners>
            <listener>
                <class>com.ramostear.cache.config.PersonCacheEventLogger</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>UPDATED</events-to-fire-on>
                <events-to-fire-on>EXPIRED</events-to-fire-on>
                <events-to-fire-on>REMOVED</events-to-fire-on>
                <events-to-fire-on>EVICTED</events-to-fire-on>
            </listener>
        </listeners>
        <resources>
                <heap unit="entries">2000</heap>
                <offheap unit="MB">100</offheap>
        </resources>
    </cache>
</config>

Finally, you need to define a cache event listener to record the system operation cache data. The fastest way is to implement the CacheEventListener interface:

package com.ramostear.cache.config;

import org.ehcache.event.CacheEvent;
import org.ehcache.event.CacheEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author ramostear
 * @create-time 2019/4/7 0007-0:48
 * @modify by :
 * @since:
 */
public class PersonCacheEventLogger implements CacheEventListener<Object,Object>{

    private static final Logger logger = LoggerFactory.getLogger(PersonCacheEventLogger.class);

    @Override
    public void onEvent(CacheEvent cacheEvent) {
        logger.info("person caching event {} {} {} {}",
                cacheEvent.getType(),
                cacheEvent.getKey(),
                cacheEvent.getOldValue(),
                cacheEvent.getNewValue());
    }
}

3. Use @ Cacheable annotation

To enable Spring Boot to cache our data, we need to annotate the business method with @ Cacheable annotation, telling Spring Boot that the data generated in this method needs to be added to the cache:

package com.ramostear.cache.service;

import com.ramostear.cache.entity.Person;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * @author ramostear
 * @create-time 2019/4/7 0007-0:51
 * @modify by :
 * @since:
 */
@Service(value = "personService")
public class PersonService {

    @Cacheable(cacheNames = "person",key = "#id")
    public Person getPerson(Long id){
        Person person = new Person(id,"ramostear","ramostear@163.com");
        return person;
    }
}

Through the above three steps, we have completed the caching function of Spring Boot. Next, we will test the actual situation of the cache.

4. Cache test

To test our application and create a simple Restful endpoint, it will call PersonService to return a Person object:

package com.ramostear.cache.controller;

import com.ramostear.cache.entity.Person;
import com.ramostear.cache.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author ramostear
 * @create-time 2019/4/7 0007-0:54
 * @modify by :
 * @since:
 */
@RestController
@RequestMapping("/persons")
public class PersonController {

    @Autowired
    private PersonService personService;

    @GetMapping("/{id}")
    public ResponseEntity<Person> person(@PathVariable(value = "id") Long id){
        return new ResponseEntity<>(personService.getPerson(id), HttpStatus.OK);
    }
}

Person is a simple POJO class:

package com.ramostear.cache.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;

/**
 * @author ramostear
 * @create-time 2019/4/7 0007-0:45
 * @modify by :
 * @since:
 */
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Person implements Serializable{

    private Long id;

    private String username;

    private String email;
}

After all the above preparations, let's compile and run the application. After the project starts successfully, open it with a browser: http://localhost:8080/persons/1 , you will see the following information in the browser page:

{"id":1,"username":"ramostear","email":"ramostear@163.com"}

At this time, observe the log information output by the console:

1. 2019-04-07 01:08:01.001  INFO 6704 --- [nio-8080-exec-1] 
o.s.web.servlet.DispatcherServlet        : Completed 
initialization in 5 ms
2. 2019-04-07 01:08:01.054  INFO 6704 --- [e [_default_]-0] 
c.r.cache.config.PersonCacheEventLogger  : person caching event 
CREATED 1 null com.ramostear.cache.entity.Person@ba8a729

Since we are requesting the API for the first time, there is no cached data. Therefore, Ehcache creates a cache of data, which can be seen through CREATED.

We set the cache expiration time to 1 minute (1) in ehcache.xml file, so we refresh the browser within one minute, and we will not see new log output. After one minute, the cache expires. We refresh the browser again, and we will see the following log output:

1. 2019-04-07 01:09:28.612  INFO 6704 --- [e [_default_]-1] 
c.r.cache.config.PersonCacheEventLogger  : person caching event 
EXPIRED 1 com.ramostear.cache.entity.Person@a9f3c57 null
2. 2019-04-07 01:09:28.612  INFO 6704 --- [e [_default_]-1] 
c.r.cache.config.PersonCacheEventLogger  : person caching event 
CREATED 1 null com.ramostear.cache.entity.Person@416900ce

The first log indicates that the cache has expired, and the second log indicates that Ehcache has recreated a cache.

Concluding remarks

In this case, the implementation of the Spring Boot application cache based on Ehcache is explained in three simple steps.

Tags: Java Spring Ehcache Maven Lombok

Posted on Sun, 29 Dec 2019 11:43:18 -0800 by man12_patil3