掌握 Spring Boot 中的缓存:技术和最佳实践

缓存是一种用于将经常访问的数据临时存储在更快的存储层(通常在内存中)中的技术,以便可以更快地满足未来对该数据的请求,从而提高应用程序的性能和效率。在 Spring Boot 中,缓存是一种简单而强大的方法,可以通过减少数据库命中、API 调用或昂贵的计算来增强应用程序性能。
在这里插入图片描述

为什么要使用缓存?

  • 改进的性能:缓存通过从更快的缓存中提供频繁请求的数据而不是重新计算或重新获取数据来减少响应时间。
  • 减少资源负载:减少数据库或外部服务等底层资源的负载。
  • 成本效率:当您的应用程序在云中运行或使用第三方服务时,减少 API 调用或数据库访问次数可以节省成本。
  • 更好的可扩展性:通过缓存,您可以通过降低后端服务的压力来允许应用程序处理更多并发请求。

在这里插入图片描述

Spring Boot中的缓存

Spring Boot 使用@Cacheable@CachePut@CacheEvict注释等提供了一个用于缓存的抽象层。这种抽象允许您轻松集成不同的缓存实现(例如 EhCache、Hazelcast、Redis 等)。
Spring Boot 缓存中的关键概念

  • 缓存存储:这是数据缓存的实际位置(内存中、Redis、EhCache 等)。
  • 缓存键:用于存储和检索缓存数据的标识符。
  • 缓存值:与缓存键关联的实际数据。
  • 缓存管理器:用于管理不同缓存实现的 Spring 抽象。

缓存操作

  • @Cacheable :缓存方法的结果。
  • @CachePut :更新缓存而不影响方法的执行。
  • @CacheEvict :从缓存中删除条目。

2.2. Spring Boot 缓存注解

@EnableCaching :此注释启用 Spring Boot 中的缓存支持。

  • 要启用缓存,您只需使用@EnableCaching注释您的主配置类。
@SpringBootApplication
@EnableCaching
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

@Cacheable :该注解用于缓存方法调用的结果。当调用@Cacheable注解的方法时,Spring会检查结果是否已经在缓存中。如果是,则返回缓存的值;否则,执行该方法,并将结果存储在缓存中。

@Cacheable("employees")
public Employee getEmployeeById(Long id) {// Simulate expensive operationreturn employeeRepository.findById(id).orElse(null);
}

@CacheEvict :这用于从缓存中删除条目。您可以指定要逐出哪个键或缓存。

@CacheEvict(value = "employees", allEntries = true)
public void clearCache() {// Clears all cache entries for 'employees'
}

@CachePut :与@Cacheable不同,此注释确保方法始终执行,但用结果更新缓存。

@CachePut(value = "employees", key = "#employee.id")
public Employee updateEmployee(Employee employee) {return employeeRepository.save(employee);
}

缓存机制工作流程

步骤1 :向带有@Cacheable注释的方法发出请求。

步骤 2 :Spring 检查缓存中的数据是否可用:

  • 如果,则返回缓存的值而不执行该方法。
  • 如果没有,则执行该方法,缓存结果,然后返回结果。

步骤3 :对于@CachePut ,执行该方法,并且无论key是否已经存在于缓存中,结果都会被缓存。

步骤4 :对于@CacheEvict ,Spring根据提供的缓存键删除缓存条目(或清除整个缓存)。

在 Spring Boot 中配置缓存存储

Spring Boot 支持多个缓存提供程序,例如:

  • ConcurrentMapCache (默认,内存缓存)
  • EhCache 高速缓存
  • Hazelcast 榛卡斯特
  • Redis 雷迪斯
  • Caffeine 咖啡因

生产场景用到的缓存中间件

在这里插入图片描述

如何在生产中应用

  • 由于其性能、集群功能、灵活性和广泛的功能, Redis通常是大多数生产环境的最佳缓存提供程序。
  • 如果您正在使用分布式系统或微服务,Redis 或Hazelcast因其可扩展性而更适合。
  • 对于易于集成和本地缓存就足够的小型单节点应用程序, EhCacheCaffeine会更易于使用。

为了演示在带有 MySQL 的 Spring Boot 应用程序中使用EhCache 的完整示例,我们将构建一个基本应用程序,该应用程序对Employee实体执行 CRUD 操作,并利用缓存来获取、更新和删除操作。

设置项目

We’ll use the following: 我们将使用以下内容:

  • 用于数据库交互的Spring Boot Starter Data JPA
  • EhCache作为缓存提供者。
  • MySQL作为数据库。

依赖关系

在您的pom.xml中,包含必要的依赖项:

<dependencies><!-- Spring Boot Starter Data JPA --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- Spring Boot Starter Cache --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><!-- EhCache --><dependency><groupId>org.ehcache</groupId><artifactId>ehcache</artifactId></dependency><!-- MySQL Driver --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Lombok (for boilerplate code) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency>
</dependencies>

EhCache配置

src/main/resources目录下创建**ehcache.xml**文件:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"><cache name="employees"maxEntriesLocalHeap="1000"timeToLiveSeconds="3600"memoryStoreEvictionPolicy="LRU"></cache>
</ehcache>

应用程序属性

application.properties中,配置 MySQL 并启用 EhCache:

# MySQL Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/employee_db
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true# EhCache Configuration
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:ehcache.xml

实体类

定义Employee实体类:

package com.example.caching.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.persistence.*;@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String department;private double salary;
}

存储库接口

创建一个扩展JpaRepository EmployeeRepository接口:

package com.example.caching.repository;import com.example.caching.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

服务层

EmployeeService中实现缓存逻辑:

package com.example.caching.service;import com.example.caching.entity.Employee;
import com.example.caching.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;import java.util.Optional;@Service
public class EmployeeService {@Autowiredprivate EmployeeRepository employeeRepository;// Fetch employee and cache the result@Cacheable(value = "employees", key = "#id")public Employee getEmployeeById(Long id) {System.out.println("Fetching from database...");Optional<Employee> employee = employeeRepository.findById(id);return employee.orElse(null);}// Update employee and update cache@CachePut(value = "employees", key = "#employee.id")public Employee updateEmployee(Employee employee) {System.out.println("Updating employee in database and cache...");return employeeRepository.save(employee);}// Delete employee and evict cache@CacheEvict(value = "employees", key = "#id")public void deleteEmployee(Long id) {System.out.println("Deleting employee from database and evicting cache...");employeeRepository.deleteById(id);}// Clear entire cache for 'employees'@CacheEvict(value = "employees", allEntries = true)public void clearCache() {System.out.println("Cache cleared!");}
}

控制器层

创建一个 REST 控制器来公开 CRUD 端点:

package com.example.caching.controller;import com.example.caching.entity.Employee;
import com.example.caching.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/employees")
public class EmployeeController {@Autowiredprivate EmployeeService employeeService;// Fetch employee by ID@GetMapping("/{id}")public Employee getEmployee(@PathVariable Long id) {return employeeService.getEmployeeById(id);}// Update employee@PutMapping("/{id}")public Employee updateEmployee(@PathVariable Long id, @RequestBody Employee employee) {employee.setId(id);return employeeService.updateEmployee(employee);}// Delete employee@DeleteMapping("/{id}")public void deleteEmployee(@PathVariable Long id) {employeeService.deleteEmployee(id);}// Clear cache@DeleteMapping("/cache/clear")public void clearCache() {employeeService.clearCache();}
}

主要应用类

通过添加@EnableCaching在 Spring Boot 应用程序中启用缓存:

package com.example.caching;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;@SpringBootApplication
@EnableCaching
public class CachingApplication {public static void main(String[] args) {SpringApplication.run(CachingApplication.class, args);}
}

测试应用程序

启动应用程序并使用 Postman(或类似工具)来访问以下端点:

获取员工(缓存结果):

GET http://localhost:8080/api/employees/{id}

第一个请求将从数据库中获取员工并缓存结果。后续对同一员工 ID 的请求将从缓存中返回结果。

更新员工(更新缓存):

PUT http://localhost:8080/api/employees/{id}

更新数据库和缓存中的员工。

删除员工(删除缓存):

DELETE http://localhost:8080/api/employees/{id}

从数据库中删除员工并删除缓存条目。

Clear Cache: 清空缓存:

DELETE http://localhost:8080/api/employees/cache/clear

清除employees的所有缓存条目。

这个完整的 Spring Boot 示例演示了如何将EhCache与 MySQL 数据库集成以缓存 CRUD 操作。 @Cacheable@CachePut@CacheEvict注释无缝处理缓存,通过减少数据库负载来提高性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/62892.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我谈冈萨雷斯对频域滤波的误解——快速卷积与频域滤波之间的关系

在Rafael Gonzalez和Richard Woods所著的《数字图像处理》中&#xff0c;Gonzalez对频域滤波是有误解的&#xff0c;在频域设计滤波器不是非得图像和滤波器的尺寸相同&#xff0c;不是非得在频域通过乘积实现。相反&#xff0c;FIR滤波器设计都是构造空域脉冲响应。一般的原则是…

AI高中数学教学视频生成技术:利用通义千问、MathGPT、视频多模态大模型,语音大模型,将4个模型融合 ,生成高中数学教学视频,并给出实施方案。

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下AI高中数学教学视频生成技术&#xff1a;利用通义千问、MathGPT、视频多模态大模型&#xff0c;语音大模型&#xff0c;将4个模型融合 &#xff0c;生成高中数学教学视频&#xff0c;并给出实施方案。本文利用专家模…

Linux下,用ufw实现端口关闭、流量控制(二)

本文是 网安小白的端口关闭实践 的续篇。 海量报文&#xff0c;一手掌握&#xff0c;你值得拥有&#xff0c;让我们开始吧&#xff5e; ufw 与 iptables的关系 理论介绍&#xff1a; ufw&#xff08;Uncomplicated Firewall&#xff09;是一个基于iptables的前端工具&#xf…

MySQL之数据完整性

数据的完整性约束可以分为三类: 实体完整性、域完整性和引用完整性。 说来说去&#xff08;说主键&#xff0c;外键&#xff0c;以及⼀些约束&#xff09; 1、实体完整性 &#xff08;实体就是行&#xff09; 什么是关系型数据库&#xff1f; 一个表代表一类事务&#xff0…

echarts的双X轴,父级居中的相关配置

前言&#xff1a;折腾了一个星期&#xff0c;在最后一天中午&#xff0c;都快要放弃了&#xff0c;后来坚持下来&#xff0c;才有下面结果。 这个效果就相当是复合表头&#xff0c;第一行是子级&#xff0c;第二行是父级。 子级是奇数个时&#xff0c;父级label居中很简单&…

配置宝塔php curl 支持http/2 发送苹果apns消息推送

由于宝塔面板默认的php编译的curl未加入http2的支持&#xff0c;如果服务需要使用apns推送等需要http2.0的访问就会失败&#xff0c;所以重新编译php让其支持http2.0 编译方法&#xff1a; 一、安装nghttp2 git clone https://github.com/tatsuhiro-t/nghttp2.git cd nghttp…

记录一次网关异常

记一次网关异常 网关时不时就会出现下面的异常。关键是不知道什么时候就会报错&#xff0c;并且有时候就算什么都不操作&#xff0c;也会导致这个异常。 ERROR org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler - Unexpected error occurred in schedul…

动态艺术:用Python将文字融入GIF动画

文章内容&#xff1a; 在数字媒体的多样化发展中&#xff0c;GIF动画作为一种流行的表达形式&#xff0c;常被用于广告、社交媒体和娱乐。本文通过一个具体的Python编程示例&#xff0c;展示了如何将文字以动态形式融入到GIF动画中&#xff0c;创造出具有视觉冲击力的动态艺术…

@antv/x6 再vue中 ,自定义图形,画流程图、数据建模、er图等图形

X6 是基于 HTML 和 SVG 的图编辑引擎&#xff0c;提供低成本的定制能力和开箱即用的内置扩展&#xff0c;方便我们快速搭建 DAG 图、ER 图、流程图、血缘图等应用。 最终效果图 1.安装 npm install antv/x6 --save //x6主要包 npm install antv/x6-vue-shape //使用vue组…

2.4特征预处理(机器学习)

2.4特征预处理 2.4.1 什么是特征预处理 通过 一些转换函数将特征数据转换成更加适合算法模型的特征数据过程。 1 包含内容 数值型数据的无量纲化&#xff1a; 归一化 标准化 2 特征预处理API sklearn.preprocessing 为什么要进行归一化/标准化&#xff1f; 特征的单…

前端、后端、测试?如何选择

目录 一、前端开发 &#xff08;一&#xff09;职业概述 &#xff08;二&#xff09;需学习的技术 二、后端开发 &#xff08;一&#xff09;职业概述 &#xff08;二&#xff09;需学习的技术 三、测试 &#xff08;一&#xff09;职业概述 &#xff08;二&#xff0…

AI - 谈谈RAG中的查询分析(2)

AI - 谈谈RAG中的查询分析&#xff08;2&#xff09; 大家好&#xff0c;RAG中的查询分析是比较有趣的一个点&#xff0c;内容丰富&#xff0c;并不是一句话能聊的清楚的。今天接着上一篇&#xff0c;继续探讨RAG中的查询分析&#xff0c;并在功能层面和代码层面持续改进。 功…

hadoop环境配置-创建hadoop用户+更新apt+安装SSH+配置Java环境

一、创建hadoop用户(在vm安装的ubantu上打开控制台) 1、sudo useradd -m hadoop -s /bin/bash &#xff08;创建hadoop用户&#xff09; 2、sudo passwd hadoop (设置密码) 3、sudo adduser hadoop sudo&#xff08;将新建的hadoop用户设置为管理员&#xff09; 执行如下图 将…

大数据新视界 -- Hive 数据湖架构中的角色与应用(上)(25 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

SpringMVC:参数传递之日期类型参数传递

环境准备和参数传递请见&#xff1a;SpringMVC参数传递环境准备 日期类型比较特殊&#xff0c;因为对于日期的格式有N多中输入方式&#xff0c;比如: 2088-08-182088/08/1808/18/2088… 针对这么多日期格式&#xff0c;SpringMVC该如何接收&#xff0c;它能很好的处理日期类…

jmeter如何导出中文版的测试报告?

文章目录 0、初始步骤&#xff1a;把报告模板换成中文形式1、首先添加一份聚合报告2、然后点开【聚合报告】3&#xff0c;生成报告3.1 选择【工具】-【generate HTML report】3.2 【generate HTML report】参数详解3.3 、最后点击 【generate report】直接生成。 声明&#xff…

基于IPD双轮驱动, 打破产品同质化竞争魔咒

在当今竞争激烈的商业环境中&#xff0c;产品同质化现象愈发严重&#xff0c;企业面临着巨大的挑战。如何在众多相似产品中脱颖而出&#xff0c;赢得客户的青睐并获取持续的竞争优势&#xff0c;成为企业亟待解决的关键问题。基于 IPD 双轮驱动的产品开发模式&#xff0c;为企业…

2.mysql 中一条更新语句的执行流程是怎样的呢?

前面我们系统了解了一个查询语句的执行流程&#xff0c;并介绍了执行过程中涉及的处理模块。 相信你还记得&#xff0c;一条查询语句的执行过程一般是经过连接器、分析器、优化器、执行器等功能模块&#xff0c;最后到达存储引擎。 那么&#xff0c;一条更新语句的执行流程又…

【LeetCode每日一题】——204.计数质数

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 数组 二【题目难度】 中等 三【题目编号】 204.计数质数 四【题目描述】 给定整数 n &…

【数据事务】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…