Spring Boot 缓存

2025年03月17日 | 阅读 9 分钟

Spring Framework 提供了在 Spring 应用程序中透明地进行缓存的功能。在 Spring 中,**缓存抽象** 是一种机制,它允许以最小的代码影响来一致地使用各种缓存方法。

缓存抽象

缓存抽象机制适用于 **Java 方法**。使用缓存抽象的主要目标是**减少**基于缓存中信息的方法执行次数。它适用于计算密集型的方法,例如**CPU**或**IO 密集型**。

每次调用方法时,抽象都会对方法应用缓存行为。它会检查该方法是否已根据给定的参数执行过。

  • 如果是,则会返回缓存的结果,而无需执行实际方法。
  • 如果不是,则首先执行方法,然后将结果缓存并返回给用户。

注意:此方法仅适用于保证对给定输入返回相同结果的方法。方法执行多少次无关紧要。

开发人员在处理缓存抽象时需要注意两件事。

  • 缓存声明:它识别需要缓存的方法。
  • 缓存配置:存储和读取数据的后端缓存。

缓存

缓存是临时内存(RAM)的一部分。它位于应用程序和持久化数据库之间。它存储最近使用过的数据,从而尽可能减少对数据库的访问次数。换句话说,缓存就是为将来引用而存储数据。

为什么要使用缓存?

使用缓存的主要原因是使数据访问更快、成本更低。当高请求资源被多次请求时,开发人员通常缓存资源以便能够快速响应。在应用程序中使用缓存可提高应用程序的性能。从内存访问数据总是比从数据库获取数据快。它可以减少金钱成本和机会成本。

应该缓存什么数据?

  • 不经常更改的数据。
  • 经常使用的、在一段时间内结果不会在每次调用时都发生变化的可读查询。

缓存类型

有**四**种类型的缓存,如下所示:

  • 内存缓存
  • 数据库缓存
  • Web 服务器缓存
  • CDN 缓存

内存缓存

内存缓存可提高应用程序的性能。这是经常使用的区域。**Memcached** 和 **Redis** 是内存缓存的示例。它在应用程序和数据库之间存储键值对。Redis 是一个**内存、分布式**的高级缓存工具,支持备份和恢复。我们也可以在分布式集群中管理缓存。

数据库缓存

数据库缓存是一种机制,它通过从数据库中获取数据来按需(动态)生成网页。它用于涉及客户端、Web 应用程序服务器和数据库的**多层**环境。它通过分发查询工作负载来提高**可伸缩性**和**性能**。最流行的数据库缓存是 Hibernate 的第一级缓存。

Web 服务器缓存

Web 服务器缓存是一种用于**重用**而存储数据的机制。例如,Web 服务器提供的网页副本。当用户首次访问页面时,它会被缓存。如果用户下次再次请求,缓存将提供该页面的副本。这可以防止服务器过载。Web 服务器缓存提高了页面交付速度,并减少了后端服务器的工作量。

CDN 缓存

**CDN** 代表**内容分发网络**。它是现代 Web 应用程序中使用的组件。通过将经常请求的文件(例如 HTML 页面、样式表、JavaScript、图像、视频等)**复制**到全局分布的**缓存服务器**集,来提高内容的交付效率。

这就是 CDN 变得越来越受欢迎的原因。CDN 减少了源应用程序的负载,并改善了用户体验。它从靠近最终用户的**缓存边缘**(一个更靠近最终用户的缓存服务器)或**接入点 (PoP)** 提供内容的本地副本。

缓存与缓冲区

缓存Buffer
缓存基于**最近最少使用 (LRU)**。缓冲区基于**先进先出 (FIFO)**。
它是页面缓存的大小。它是一个内存中的原始块 I/O 缓冲区。
它会**长时间**存在。它会**短时间**存在。
我们从缓存中**读取**。我们**写入**缓冲区。
它存储**实际**的文件数据。它存储文件的**元数据**。
它提高了**读取**性能。它提高了**写入**性能。

Spring Boot 缓存注解

@EnableCaching

这是一个类级别的注解。我们可以使用 **@EnableCaching** 注解在 Spring Boot 应用程序中启用缓存。它定义在 **org.springframework.cache.annotation** 包中。它与 **@Configuration** 类一起使用。

自动配置会在没有已定义的 CacheManager 实例时启用缓存并设置一个 **CacheManager**。它会扫描特定的提供程序,如果找不到,它会使用并发 **HashMap** 创建一个内存缓存。

示例

在以下示例中,**@EnableCaching** 注解启用了缓存机制。

@CacheConfig

这是一个类级别的注解,提供通用的缓存相关设置。它告诉 Spring 在哪里为该类存储缓存。当我们用注解注解一个类时,它为该类中定义的任何缓存操作提供了一组默认设置。使用此注解,我们无需多次声明内容。

示例

在以下示例中,**employee** 是缓存的名称。

@Caching

当我们想要在同一方法上同时使用 **@CachePut** 或 **@CacheEvict** 这两个注解时使用。换句话说,当我们想使用多个相同类型的注解时使用。

但是**Java 不允许在一个方法上声明多个相同类型的注解**。为了避免这个问题,我们使用 **@Caching** 注解。

示例

在以下示例中,我们使用了 **@Caching** 注解,并将所有 **@CacheEvict** 注解分组。

@Cacheable

这是一个方法级别的注解。它为方法的返回值定义了一个缓存。Spring Framework 管理方法到注解属性中指定的缓存的请求和响应。@Cacheable 注解包含更多选项。例如,我们可以使用 **value** 或 **cacheNames** 属性来提供**缓存名称**。

我们还可以指定注解的**key** 属性,该属性唯一标识缓存中的每个条目。如果我们不指定 key,Spring 会使用默认机制来创建 key。

示例

在下面的示例中,我们将方法 **studentInfo()** 的**返回值**缓存到 **cacheStudentInfo** 中,并且 **id** 是唯一标识缓存中每个条目的 key。

我们还可以使用 condition 属性在注解中应用条件。当我们应用条件到注解时,它被称为**条件缓存**。

例如,如果参数 name 的长度小于 20,则以下方法将被缓存。

@CacheEvict

这是一个方法级别的注解。当我们想要从缓存中删除过时或未使用的 Dàtǎ 时使用。它需要一个或多个受操作影响的缓存。我们也可以在其中指定 key 或 condition。如果我们想要广泛的缓存驱逐,@CacheEvict 注解提供了一个名为 **allEntries** 的参数。它会驱逐所有条目,而不是基于 key 的单个条目。

关于 @CacheEvict 注解的一个重要提示是,它可以与 void 方法一起使用,因为该方法充当触发器。它不返回任何值。另一方面,@Cacheable 注解需要一个返回值来添加/更新缓存中的数据。我们可以通过以下方式使用 @CacheEvict 注解:

驱逐整个缓存

按 key 驱逐条目

示例

以下注解的方法会从缓存 **student_data** 中驱逐所有数据。

@CachePut

这是一个方法级别的注解。当我们想在不干扰方法执行的情况下**更新**缓存时使用。这意味着方法总是会执行,并且其结果将被放入缓存。它支持 @Cacheable 注解的属性。

需要注意的是,@Cacheable 和 @CachePut 注解的行为不同。@Cacheable 和 @CachePut 注解之间有一个细微的差别是,**@Cacheable** 注解会**跳过方法执行**,而 **@CachePut** 注解会**运行方法**并将结果放入缓存。

示例

以下方法将更新缓存本身。

Spring Boot 缓存依赖

如果我们想在 Spring Boot 应用程序中启用缓存机制,我们需要在 pom.xml 文件中添加缓存依赖。它会启用缓存并配置一个 CacheManager。

Spring Boot 缓存示例

让我们创建一个 Spring Boot 应用程序并实现其中的缓存机制。

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

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

步骤 2:提供Group 名称。我们提供了 com.javatpoint。

步骤 3:提供 **Artifact** ID。我们提供了 **spring-boot-cache-example**。

步骤 5:添加 **Spring Web** 和 **Spring Cache Abstraction** 依赖。

步骤 6: 单击 Generate 按钮。当我们单击 Generate 按钮时,它将规范包装在一个 Jar 文件中,并将其下载到本地系统。

步骤 7:**解压** Jar 文件并粘贴到 STS 工作区。

步骤 8:在 STS 中**导入**项目文件夹。

File -> Import -> Existing Maven Projects -> Browse -> Select the folder spring-boot-cache-example -> Finish

它需要一些时间来导入。

让我们打开 **pom.xml** 文件,看看我们向其中添加了哪些依赖项。

pom.xml

步骤 9:打开 **SpringBootCacheExampleApplication.java** 文件,并通过添加 **@EnableCaching** 注解来启用缓存。

步骤 10:在 **src/main/java** 文件夹中创建一个名为 **com.javatpoint.model** 的包。

步骤 11:在 model 包中,创建一个名为 **Customer** 的类并进行以下操作:

  • 定义三个变量 **accountno, customername, acounttype,** 和 **balance**。
  • 生成**包含字段的构造函数**。
    右键单击该文件 -> Source -> Generate Constructor using Fields -> Select All -> Generate
  • 生成 Getters 和 Setters(Getter 和 Setter 方法)。
    右键单击该文件 -> Source -> Generate Getters and Setters -> Select All -> Generate

Customer.java

步骤 11:在 **src/main/java** 文件夹中创建一个名为 **com.javatpoint.controller** 的包。

步骤 12:在 Controller 包中,创建一个名为 **CustomerController** 的控制器类并执行以下操作:

  • 使用 **@RestController** 注解将该类标记为**控制器**。
  • 使用 **@RequestMapping** 注解为控制器定义**映射**。我们定义了映射 **\customerinfo**。
  • 使用 **@Cacheable** 注解创建一个**缓存**来获取数据。我们使用注解的 **value** 属性定义了缓存名称。
  • 我们在

CustomerController.java

现在运行应用程序。

步骤 13:打开 **SpringBootCacheExampleApplication.java** 文件并将其作为 Java 应用程序运行。

步骤 14:打开 **Postman** 并发送一个 **GET** 请求,URL 为 http://locahost:8080/custmerinfo。它将返回客户详细信息,如下所示。

Spring Boot Caching