Spring boot教程-Spring Boot EhCache
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(集群存储)
它在远程服务器上存储缓存条目。它比堆外存储慢。它可能具有故障转移服务器,以提供高可用性。
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>
现在我们已经创建了所有所需的文件。完成所有文件创建后,项目目录如下所示:
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]