Spring Boot EhCache EhCache EhCache是一个开源的基于Java的缓存,用于提升性能。目前的EhCache版本是3。它提供了JSR-107缓存管理器的实现。我们可以直接使用它。

EhCache的特点

  • 它快速、轻量、可扩展和灵活。
  • 它允许我们执行Serializable和Object类型的缓存。
  • 它提供了LRU、LFU、FIFO等缓存逐出策略。
  • 它将缓存存储在内存和磁盘(SSD)中。
  • 它依赖于SLF4J进行日志记录。
  • 它完全实现了JSR-107和JCache规范。
  • 它通过JGroups、JMS和RMI支持分布式缓存。
  • 它使用流畅的查询语言进行分布式搜索。

EhCache使用模式

EhCache使用了几种访问模式。以下是EhCache使用的模式:

  • Cache-aside(旁路缓存)
  • Cache-as-SoR(系统记录)
  • Read-through(读取穿透)
  • Write-through(写入穿透)
  • Write-behind(写入后置)

Cache-aside(旁路缓存)

在旁路缓存模式中,应用程序首先与缓存进行交互。如果找到数据,直接返回数据。在相反的情况下,它从SoR(系统记录)中获取数据,将其存储在缓存中,然后返回。

Cache-as-SoR(系统记录)

Cache-as-SoR模式表示将SoR的读取和写入操作放入缓存中。它减轻了应用程序的责任。它使用了读取和写入模式的组合,包括读取穿透、写入穿透和写入后置。它降低了应用程序的复杂性。它允许缓存解决"thundering-herd"问题。

Read-through(读取穿透)

读取穿透模式在从缓存中读取数据时也采用了旁路缓存模式。读取穿透模式与旁路缓存模式的区别在于,读取穿透模式实现了CacheEntryFactory接口。它指导缓存如何从缓存中读取对象。在使用读取穿透模式时,最好将EhCache实例包装在SelfPopulatingCache实例中。

Write-through(写入穿透)

写入穿透模式在将数据写入缓存时也采用了旁路缓存模式。写入穿透模式与旁路缓存模式的区别在于,写入穿透模式实现了CacheWriter接口。它为缓存配置了写入穿透和写入后置模式。它将数据写入SoR中,使用的是同一线程的执行。

Write-behind(写入后置)

写入后置模式与其他三种模式不同。它在可配置的延迟时间后修改缓存条目。延迟时间可以是秒、分钟、天、周,或者长时间。同时,它也会将数据排队以便稍后在同一线程中写入。

使用写入后置模式写入的数据在事务的范围之外进行。这意味着它会创建一个新的事务来提交与主事务不同的SoR中的数据。

EhCache存储层次 EhCache允许我们使用各种数据存储区域,如堆内存、磁盘和集群。我们可以配置一个多存储区的缓存(使用多个存储区域)。它可以按层次进行排列和管理。

这些层次按顺序组织。最底部的层次称为"authority tier",其他层次称为"caching tier"。caching tier也称为"nearer"或"near cache"。caching tier可以有多个存储区。最热门的数据保留在caching tier中,因为它比authority tier更快。其他数据保留在authority tier中,相对于caching tier来说速度较慢,但更丰富。

EhCache支持四种类型的数据存储:

  • On-Heap Store(堆内存存储)
  • Off-Heap Store(堆外存储)
  • Disk Store(磁盘存储)
  • Clustered Store(集群存储)

On-Heap Store(堆内存存储)

它将缓存条目存储在Java堆内存中。它与Java应用程序共享存储。它速度很快,因为它使用堆内存,但存储空间有限。垃圾回收器也会扫描堆内存存储。

Off-Heap Store(堆外存储)

它使用主内存(RAM)存储缓存条目。垃圾回收器不会扫描它。它比堆内存存储(on-heap store)慢,因为缓存条目在使用之前会移动到堆内存存储。它的大小受限。

Disk Store(磁盘存储)

它使用磁盘存储缓存条目。它比基于RAM的存储(堆内存和堆外存储)慢得多。如果使用磁盘存储模式,最好使用专用磁盘。它增加了吞吐量。

Clustered Store(集群存储)

它在远程服务器上存储缓存条目。它比堆外存储慢。它可能具有故障转移服务器,以提供高可用性。

f12ba3f64d06f2a829bc0b359852f87.png

Spring Boot EhCaching 上图显示了:

  • 一个应用程序可以有多个Cache Manager。
  • 一个Cache Manager可以处理多个缓存。
  • 缓存可以使用多个层次来存储缓存条目。
  • EhCache将最近使用或频繁使用的数据放在更快的层次(caching tier)中。

配置EhCache

1.将EhCache jar文件放置在类路径中。
2.配置xml文件并将其放置在类路径中。
3.创建引用缓存。
4.EhCache示例

在下面的示例中,我们将在应用程序中配置EhCache。

步骤1:打开Spring Initializr https://start.spring.io/

步骤2:选择Spring Boot版本2.3.0 M2。

步骤3:提供Group名称。我们提供的Group名称是cn.javatiku。

步骤4:提供Artifact。我们提供的Artifact是spring-boot-ehcache-example。

步骤5:添加Spring Web依赖。

步骤6:点击Generate按钮。点击Generate按钮后,它将所有与应用程序相关的规格封装到一个Jar文件中,并将其下载到本地系统。

步骤7:解压缩jar文件。

步骤8:复制该文件夹并粘贴到STS工作区。

步骤9:导入项目。

File -> Import -> Existing Maven Projects -> Next -> Browse -> 选择文件夹spring-boot-ehcache-example -> 选择文件夹 -> 完成

导入项目需要一些时间。

步骤10:逐一从Maven Repository https://mvnrepository.com/复制以下依赖项,并将其粘贴到pom.xml文件中。

  • spring-boot-starter-cache
  • ehcache 3
  • cache API。

注意:不要使用net.sf.ehcache包中的ehcache。

pom.xml

<?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 https://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.3.0.M2</version>  
<relativePath/> <!-- lookup parent from repository -->  
</parent>  
<groupId>cn.javatiku</groupId>  
<artifactId>spring-boot-ehcache-example</artifactId>  
<version>0.0.1-SNAPSHOT</version>  
<name>spring-boot-ehcache-example</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-web</artifactId>  
</dependency>  
<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>  
<dependency>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-starter-test</artifactId>  
<scope>test</scope>  
<exclusions>  
<exclusion>  
<groupId>org.junit.vintage</groupId>  
<artifactId>junit-vintage-engine</artifactId>  
</exclusion>  
</exclusions>  
</dependency>  
</dependencies>  
<build>  
<plugins>  
<plugin>  
<groupId>org.springframework.boot</groupId>  
<artifactId>spring-boot-maven-plugin</artifactId>  
</plugin>  
</plugins>  
</build>  
<repositories>  
<repository>  
<id>spring-milestones</id>  
<name>Spring Milestones</name>  
<url>https://repo.spring.io/milestone</url>  
</repository>  
</repositories>  
<pluginRepositories>  
<pluginRepository>  
<id>spring-milestones</id>  
<name>Spring Milestones</name>  
<url>https://repo.spring.io/milestone</url>  
</pluginRepository>  
</pluginRepositories>  
</project>  

现在,我们需要配置ehcache.xml文件,它告诉框架在哪里找到该文件。

步骤11:打开application.properties文件,并通过以下属性配置EhCache。

application.properties

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

步骤12:打开SpringBootEhcacheExampleApplication.java文件,并使用注解@EnableCaching启用缓存。

SpringBootEhcacheExampleApplication.java

package cn.javatiku;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.cache.annotation.EnableCaching;  
@SpringBootApplication  
//enables the cache management capability  
@EnableCaching  
public class SpringBootEhcacheExampleApplication   
{  
public static void main(String[] args)   
{  
SpringApplication.run(SpringBootEhcacheExampleApplication.class, args);  
}  
}  

注意:如果不想在主应用程序文件中使用@EnableCaching注解,可以创建一个单独的CacheConfig类,并在该类上注解。

package cn.javatiku;  
import org.springframework.cache.annotation.EnableCaching;  
import org.springframework.context.annotation.Configuration;  
@Configuration  
//enable caching  
@EnableCaching  
public class CacheConfig   
{  
}  

步骤13:创建一个管理学生的Service类。我们创建了名为StudentManager的service类。在此类中,我们完成了以下工作:

  • 使用注解@Service注解了类。
  • 创建一个HashMap的实例。
  • 在静态块中,我们向map中添加了学生数据。
  • 使用@Cacheable注解,我们定义了缓存的名称,所有数据都将保存在该缓存中。我们在注解的key属性中定义了id。缓存根据id搜索学生。
  • 我们创建了一个方法getStudentById(),该方法将id作为参数。它返回学生的id。

Student.java

package cn.javatiku;  
public class Student   
{  
private int id;  
private String name;  
private String gender;  
private String city;  
public Student(int id, String name, String gender, String city)   
{  
super();  
this.id = id;  
this.name = name;  
this.gender = gender;  
this.city = city;  
}  
public int getId()   
{  
return id;  
}  
public void setId(int id)   
{  
this.id = id;  
}  
public String getName()   
{  
return name;  
}  
public void setName(String name)   
{  
this.name = name;  
}  
public String getGender()   
{  
return gender;  
}  
public void setGender(String gender)   
{  
this.gender = gender;  
}  
public String getCity()   
{  
return city;  
}  
public void setCity(String city)   
{  
this.city = city;  
}  
@Override  
public String toString()   
{  
return "Student [id=" + id + ", name=" + name + ", gender=" + gender + ", city=" + city + "]";  
}  
}   

步骤14:创建一个用于管理学生的Service类。我们创建了名为StudentManager的service类。在这个类中,我们完成了以下工作:

1.使用注解@Service对类进行了标注。
2.创建了一个HashMap的实例。
3.在静态块中,我们将学生数据添加到了map中。
4.使用@Cacheable注解,我们定义了缓存的名称,所有的数据都将保存在这个缓存中。我们在注解的key属性中定义了id。缓存根据id搜索学生。
5.我们创建了一个方法getStudentById(),该方法将id作为参数解析。它返回学生的id。

StudentManager.java

StudentManager.java  
package cn.javatiku;  
import java.util.HashMap;  
import org.springframework.cache.annotation.Cacheable;  
import org.springframework.stereotype.Service;  
@Service  
public class StudentManager   
{  
static HashMap<Integer, Student> student = new HashMap<>();  
static   
{  
student.put(1, new Student(100, "Alex", "Male", "Berlin"));  
student.put(2, new Student(101, "Tony", "Male", "Maxico"));  
student.put(3, new Student(102, "Andrew", "Male", "Chicago"));  
student.put(4, new Student(103, "Alexa", "Female", "Brussels"));  
student.put(5, new Student(104, "Maria", "Female", "Houston"));  
}  
@Cacheable(cacheNames="demoCache", key="#id")  
public Student getStudentById(Integer id)   
{  
System.out.println("Fetching student data from cache");  
return student.get(id);  
}  
}  

现在我们需要创建ehcache.xml文件。它包含与缓存相关的信息,例如缓存的名称、内存中的元素数、缓存中数据的存活时间等。

步骤15:在src/main/resources文件夹中创建名为ehcache.xml的缓存配置文件。

ehcache.xml

<config  
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'  
xmlns='http://www.ehcache.org/v3'  
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'>  
<ehcache>  
<diskStore path="java.io.tmpdir" />  
<defaultCache maxElementsInMemory="2000"   
            eternal="true"  
            overflowToDisk="false"   
            timeToLiveSeconds="1200" />  
    <cache name="demoCache"   
            maxElementsInMemory="2000"  
            eternal="false"   
            overflowToDisk="false"   
            timeToLiveSeconds="10000" />  
</ehcache>  
</config>  

现在我们已经创建了所有所需的文件。完成所有文件创建后,项目目录如下所示:
07f46ef3d5f35e9a69d6ceff7dbb889.png

Spring Boot EhCaching

让我们运行该应用程序。

步骤16:打开SpringBootEhcacheExampleApplication.java文件,并将其作为Java应用程序运行。

它将显示以下输出:

Getting Students from Cache  
[id=100, name=Alex, gender=Male, city=Berlin]  
[id=101, name=Tony, gender=Male, city=Mexico]  
[id=102, name=Andrew, gender=Male, city=Chicago]  
[id=103, name=Alexa, gender=Female, city=Brussels]  
[id=104, name=Maria, gender=Female, city=Houston]  

标签: spring, Spring教程, Spring语言学习, Spring框架, Spring框架教程, Spring框架高级教程, spring boot, spring boot入门教程, spring boot学习教程, spring boot下载, spring boot框架入门, spring boot面试题, spring boot笔试题, spring boot技术, 习指南