# Spring Boot 2 和 ehcache 3 示例

> 原文： [https://howtodoinjava.com/spring-boot2/ehcache3-config-example/](https://howtodoinjava.com/spring-boot2/ehcache3-config-example/)

学习使用 **ehcache 3.x** 在 [spring boot](https://howtodoinjava.com/spring-boot-tutorials/) 应用程序中配置缓存。 学习使用 [**基于注解的缓存配置**](https://howtodoinjava.com/spring-boot2/spring-boot-cache-example/) ，以及使用[`CacheManager`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/CacheManager.html)手动更新缓存。

## 1\. Maven 依赖

在此示例中，我们使用的是 Spring 运行版本`2.1.6.RELEASE`。 较早的 spring boot 版本支持`net.sf.ehcache`软件包下的`ehcache 2.x`。 Spring Boot 支持`ehcache 3.x`的新版本可在`org.ehcache`软件包下获得。

Ehcache 版本 3 是 [JSR-107](https://www.jcp.org/en/jsr/detail?id=107) 缓存管理器的实现。

我们需要以下依赖项来添加缓存功能。

*   `spring-boot-starter-cache`
*   **ehcache** （`org.ehcache`）
*   **缓存 API** （`javax.cache`）

`pom.xml`

```java
<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.company</groupId>
	<artifactId>SpringBootEhcache</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>SpringBootEhcache</name>
	<url>http://maven.apache.org</url>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.6.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<skipTests>true</skipTests>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>
		<dependency>
			<groupId>org.ehcache</groupId>
			<artifactId>ehcache</artifactId>
		</dependency>
		<dependency>
			<groupId>javax.cache</groupId>
			<artifactId>cache-api</artifactId>
		</dependency>
	</dependencies>

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

```

## 2\. `application.properties`

Spring 的自动配置可以找到 Ehcache 的 JSR-107 实现。 但是，默认情况下不会创建任何缓存，因为 Spring 和 Ehcache 都不会寻找默认的`ehcache.xml`文件。 我们必须专门提供必须使用的 ehcache 配置文件路径。

`application.properties`

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

```

## 3\. `ehcache.xml`

在`ehcache.xml`文件中，配置缓存名称及其属性。

在[ ehcache 文档](https://www.ehcache.org/documentation/3.0/107.html#supplement-jsr-107-configurations)中找到属性的完整列表。

`ehcache.xml`

```java
<config
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.ehcache.org/v3'
        xmlns:jsr107='http://www.ehcache.org/v3/jsr107'>

    <service>
        <jsr107:defaults enable-statistics="true"/>
    </service>

    <cache alias="employeeCache">
        <key-type>java.lang.Long</key-type>
        <value-type>com.company.Employee</value-type>
        <expiry>
            <ttl unit="seconds">10000</ttl>
        </expiry>
        <listeners>
            <listener>
                <class>com.company.CustomCacheEventLogger</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>

```

## 4\. `CacheEventListener`

我们还使用了事件监听器，该事件监听器将在创建，删除或更新缓存条目时记录缓存事件。

`CustomCacheEventLogger.java`

```java
package com.company;

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

public class CustomCacheEventLogger implements CacheEventListener<Object, Object> {

	private static final Logger LOG = LoggerFactory.getLogger(CustomCacheEventLogger.class);

	@Override
	public void onEvent(CacheEvent cacheEvent) {
		LOG.info("Cache event = {}, Key = {},  Old value = {}, New value = {}", cacheEvent.getType(),
				cacheEvent.getKey(), cacheEvent.getOldValue(), cacheEvent.getNewValue());
	}
}

```

## 5\. `@EnableCaching`

它启用 Spring 的注解驱动的缓存管理功能，并在调用[`@Cacheable`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/annotation/Cacheable.html)注解方法时启用对代理拦截器的支持。

`CacheConfig.java`

```java
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
public class CacheConfig {

}

```

## 6\. `@Cacheable`注解

要缓存从方法调用返回的数据，我们可以在方法上使用`@Cacheable`注解。 使用其属性`cacheNames`和`key`来指代缓存和缓存条目的键属性。

`EmployeeManager.java`

```java
import java.util.HashMap;

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

@Service
public class EmployeeManager 
{
	static HashMap<Long, Employee> db = new HashMap<>();

	static {
		db.put(1L, new Employee(1L, "Alex", "Gussin"));
		db.put(2L, new Employee(2L, "Brian", "Schultz"));
	}

	@Cacheable(cacheNames="employeeCache", key="#id")
	public Employee getEmployeeById(Long id) {
		System.out.println("Getting employee from DB");
		return db.get(id);
	}
}

```

## 7\. Spring `CacheManager` API

有时，在使用注解似乎不是完美解决方案的情况下，我们可能需要使用缓存。 在这种情况下，我们可以使用`org.springframework.cache.CacheManager`和`org.springframework.cache.Cache`抽象来访问并利用 ehcache 添加和访问缓存条目。

要使用`CacheManager`，我们必须首先自动装配到 spring 组件中，并使用它的`getCache(name)`方法来按名称获取缓存实例。

访问缓存后，我们可以使用其`get()`和`put()`方法来添加和访问缓存条目。

```java
//1

@Autowired
private CacheManager cacheManager;

//2

Cache cache = cacheManager.getCache("myCache");
cache.put(3L, "Hello");
String value = cache.get(3L).get();

```

## 8\. Spring Boot ehcache 3 示例 – 演示

我正在创建一个模型类`Employee`，其实例将被缓存。

`Employee.java`

```java
import java.io.Serializable;

public class Employee implements Serializable 
{
	private static final long serialVersionUID = 5517244812959569947L;

	private Long id;
	private String firstName;
	private String lastName;

	public Employee() {
		super();
	}

	public Employee(Long id, String firstName, String lastName) {
		super();
		this.id = id;
		this.firstName = firstName;
		this.lastName = lastName;
	}

	//Getters and setters

	@Override
	public String toString() {
		return "Employee [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]";
	}
}

```

现在在演示应用程序类中，我正在使用`@Cacheable`注解测试基于注解的缓存访问，并使用`CacheManager`进行手动缓存访问。

`Application.java`

```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

	@Autowired
	private CacheManager cacheManager;

	@Autowired
	private EmployeeManager employeeManager;

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

	@Bean
	public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
		return args -> {

			//This will hit the database 
			System.out.println(employeeManager.getEmployeeById(1L));

			//This will hit the cache - verify the message in console output 
			System.out.println(employeeManager.getEmployeeById(1L));

			//Access cache instance by name
			Cache cache = cacheManager.getCache("employeeCache");

			//Add entry to cache
			cache.put(3L, new Employee(3L, "Charles", "Dave"));

			//Get entry from cache
			System.out.println(cache.get(3L).get());
		};
	}
}

```

程序输出。

`Console`

```java
//First hit to "employeeManager.getEmployeeById(1L)"

Getting employee from DB
Employee [id=1, firstName=Alex, lastName=Gussin]
2019-07-10 15:42:32.371  INFO 11956 --- [e [_default_]-0] com.company.CustomCacheEventLogger       
: Cache event = CREATED, Key = 1,  Old value = null, New value = Employee [id=1, firstName=Alex, lastName=Gussin]

//Second hit to "employeeManager.getEmployeeById(1L)"
Employee [id=1, firstName=Alex, lastName=Gussin]

//cache.put(3L, new Employee(3L, "Charles", "Dave"));
2019-07-10 15:42:32.399  INFO 11956 --- [e [_default_]-0] com.company.CustomCacheEventLogger       : Cache event = CREATED, Key = 3,  Old value = null, New value = Employee [id=3, firstName=Charles, lastName=Dave]

//System.out.println(cache.get(3L).get());
Employee [id=3, firstName=Charles, lastName=Dave]

```

请在评论中使用 ehcache 3 将有关此 **spring boot 2** 缓存示例的问题交给我。

学习愉快！

[下载源码](https://howtodoinjava.com/wp-content/downloads/SpringBootCacheDemo-ehcache2.zip)