基于SpringCache实现数据缓存

SpringCache

SpringCache是一个框架实现了基本注解的缓存功能,只需要简单的添加一个@EnableCaching 注解就能实现缓存功能

  • SpringCache框架只是提供了一层抽象,底层可以切换CacheManager接口的不同实现类即使用不同的缓存技术,默认的实现是ConcurrentMapCacheManager
  • ConcurrentMapCacheManager是基于内存存储数据的,所以重启服务后缓存数据就会消失
CacheManger描述
EhCacheCacheManager使用EhCache作为缓存技术
GuavaCacheManager使用Googke的GuavaCache作为缓存技术
RedisCacheManager使用Rdis作为缓存技术

环境准备

第一步: 定义实体类User且实现序列化接口

@Data
public class User implements Serializable {private static final long serialVersionUID = 1L;private Long id;private String name;private int age;private String address;
}

第二步: 定义Mapper接口

@Mapper
public interface UserMapper extends BaseMapper<User>{
}

第三步: 定义UserService接口及其实现类

public interface UserService extends IService<User> {}@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {}

第四步: 定义接口

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {// 默认的实现是ConcurrentMapCacheManager@Autowiredprivate CacheManager cacheManager;@Autowiredprivate UserService userService;
}

第五步: 开启缓存注解功能

@Slf4j
@SpringBootApplication
// 开启缓存注解功能
@EnableCaching
public class CacheDemoApplication {public static void main(String[] args) {SpringApplication.run(CacheDemoApplication.class,args);log.info("项目启动成功...");}
}

SpringCache常用注解

因为缓存的数据key一定是唯一的,所以key支持SpEL表达式来动态的计算key(条件判断也支持SpEL表达式)

  • #result: 代表方法的返回值,如#result.id表示获取返回值对象的id属性值作为key
  • #root: 代表整个方法对象,如#root.args[0].id表示获取方法的第一个参数的id属性值作为key
  • #p[i]: 代表方法的参数,如p[0].id表示获取方法的第一个参数的id属性值作为key
  • #方法参数名: 代表方法的参数,如#user.id获取参数user对象的id属性值作为key

condition和unless的区别

  • condition: 表示满足条件才进行缓存,不支持SpEL表达式中的#result
  • unless: 表示满足条件不进行缓存,支持SpEL表达式中的#result
注解说明
@EnableCaching开启缓存注解功能
@Cacheable在方法执行前spring先查看缓存中是否有数据,如果有数据则直接返回缓存数据;若没有数据调用方法并将方法返回值放到缓存中(查询方法)
@CachePut将方法的返回值放到缓存中(适合新增的方法)
@CacheEvict将一条或者多条数据从缓存中删除(适合删除和更新的方法啊)

@CachePut(新增)

@CachePut主要针对方法配置,能够根据方法的请求参数将方法的返回值进行缓存,每次都会触发真实方法的调用

注解说明举例
value指定缓存的名称必须指定至少一个@Cacheable(value=”mycache”)或者@Cacheable(value=(“cache7”, “cache2”]
key指定缓存的key(可以为空),但必须是动态唯一的,表示某类缓存中的一个具体数据@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)

测试新增的方法将方法的返回值进行缓存

在这里插入图片描述

@CachePut(value="userCache",key="#user.id")
@PostMapping
public User save(User user){userService.save(user);return user;
}

查看ConcurrentMapCacheManager中缓存的结果

在这里插入图片描述

@CachEvict(删除)

@CachEvict主要针对方法配置,能够根据一定的条件将缓存中的数据进行清空

注解说明举例
value缓存的名称必须指定且至少一个@Cacheable(value=”mycache”)或者@Cacheable(value={“cache1”, “cache2”]
key指定缓存的key(可以为空),但必须是动态唯一的@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
allEntries是否清空某类缓存下的所有数据,默认为false@CachEvict(value=”testcache”,allEntries=true)
beforelnvocation是否在方法执行前就清空,缺省为false,如果指定为true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存@CachEvict(value=”testcache”, beforelnvocation=true)

测试删除的方法清楚缓存中指定的key

在这里插入图片描述

@CachEvict(value="userCache",key="#user.id")
@DeleteMapping("/{id}")
public void delete(@PathVariable Long id){userService.removeById(id);
}

测试更新的方法清楚缓存中指定的key

在这里插入图片描述

@CachEvict(value="userCache",key="#id")
@PutMapping
public User update(User user){userService.updateById(user);return user;
}

@Cacheable(查询)

@Cacheable注解主要针对方法配置,如果缓存中没有数据能够根据方法的请求参数对方法结果进行缓存,如果缓存中有数据则不会调用方法

  • 如果查询的数据在数据库中也查询不到则会缓存一个null,这样下次再查询这个数据时直接返回null,避免缓存穿透
注解说明举例
value指定缓存的名称表示一类缓存,每个缓存名称下可以存储多个key@Cacheable(value=”mycache”)或者@Cacheable(value=(“cache7”, “cache2”]
key(唯一)指定缓存数据的key(可以为空),表示某类缓存中的一个具体数据@Cacheable(value=”testcache”,key=”#userName”)
condition指定缓存的条件(可以为空)返回true或者false,满足条件才进行缓存@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
unless指定缓存的条件(可以为空)返回true或者false,满足条件不进行缓存@Cacheable(value=”testcache”,unless=”#userName.length()>2”)

测试根据id查询的方法,如果缓存中没有数据则将方法返回值进行缓存,如果缓存中有对应数据则不调用方法直接返回缓存的数据

在这里插入图片描述

@Cacheable(value="userCache",key="#id")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){User user = userService.getById(id);return user;
}
// 查询结果为null不缓存,condition不支持#result
@Cacheable(value="userCache",key="#id",unless="#result==null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){User user = userService.getById(id);return user;
}

测试根据多个条件进行查询的方法,不同的查询条件对应不同的缓存数据

在这里插入图片描述

@Cacheable(value="userCache",key="#user.id+'_'+#user.name")//查询条件和id和name有关
@GetMapping("/list")
public List<User> list(User user){LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(user.getId() != null,User::getId,user.getId());queryWrapper.eq(user.getName() != null,User::getName,user.getName());List<User> list = userService.list(queryWrapper);return list;
}

查询缓存的结果

在这里插入图片描述

使用SpringCache基于redis

使用步骤

第一步: 在SpringBoot项目中使用缓存技术只需要在项目中导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存技术支持即可

  • 如果想使用SpringCache的基本功能只需要导入spring-context依赖即可(导入spring-boot-starter-web会自动传递)
<!--使用Redis作为缓存技术,里面包含CacheManager接口的实现类-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--对SpringCache中CacheManager接口的实现类进行了扩展-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

第二步: 在application.yml文件中配置redis相关的配置

spring:redis:host: 101.XXX.XXX.160 #redis服务所在地址password: rootport: 6379database: 0cache:redis:time-to-live: 3600000 #设置缓存有效期为一小时(单位毫秒),如果不设置则一直存活
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {// 底层实现是RedisCacheManager@Autowiredprivate CacheManager cacheManager;@Autowiredprivate UserService userService;
}

第三步: 在启动类上加@EnableCaching注解表示开启缓存注解功能

@Slf4j
@SpringBootApplication
// 开启缓存注解功能
@EnableCaching
public class CacheDemoApplication {public static void main(String[] args) {SpringApplication.run(CacheDemoApplication.class,args);log.info("项目启动成功...");}
}

第四步: 在Controller的方法上加上@Cacheable,@CachePut,@CacheEvict缓存注解进行缓存操作

在这里插入图片描述

// 查询结果为null不缓存,condition不支持#result
@Cacheable(value="userCache",key="#id",unless="#result==null")
@GetMapping("/{id}")
public User getById(@PathVariable Long id){User user = userService.getById(id);return user;
}

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

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

相关文章

20240313寻找集成联调交付的具体方式

集成联调交付&#xff08;Integrated Joint Debugging and Delivery&#xff09;是软件开发过程中的一个阶段&#xff0c;主要涉及将不同的软件模块或组件整合在一起&#xff0c;并进行联合调试和测试&#xff0c;以确保它们能够作为一个整体正常工作。这个过程通常发生在开发周…

云仓酒庄北京朝阳区旗舰店发布活动盛况:红酒品鉴沙龙共筑美好

原标题&#xff1a;云仓酒庄北京朝阳区旗舰店活动盛况&#xff1a;红酒品鉴沙龙与招商交流共筑美好未来 在繁忙的都市中&#xff0c;有一片静谧的天地&#xff0c;那便是云仓酒庄北京朝阳区旗舰店。这里不仅是红酒爱好者的聚集地&#xff0c;更是商业交流的新平台。近日&#…

C编程基础四十分笔记

都是一些基础的C语言 一 输入一个整数&#xff0c;计算这个整数有几位二 编写程序计算一个分布函数三 输入一个字符串&#xff0c;再随便输入一个字母&#xff0c;判断这个字母出现几次四 求 1到10的阶乘之和五 求一个球体体积六 写一个链表&#xff0c;存1&#xff0c;2&#…

BUGKU-WEB never_give_up

题目描述 题目截图如下&#xff1a; 进入场景看看&#xff1a; 解题思路 F12查看请求和响应&#xff0c;查找线索 相关工具 base64解码URL解码Burp Suit抓包 解题步骤 F12查看请求和响应&#xff0c;发现一行注释包含一个文件名称【1p.html】&#xff0c;这应该就是提…

【目标检测经典算法】R-CNN、Fast R-CNN和Faster R-CNN详解系列一:R-CNN图文详解

学习视频&#xff1a;Faster-RCNN理论合集 概念辨析 在目标检测中&#xff0c;proposals和anchors都是用于生成候选区域的概念&#xff0c;但它们在实现上有些许不同。 Anchors&#xff08;锚框&#xff09;&#xff1a; 锚框是在图像中预定义的一组框&#xff0c;它们通常以…

Linux环境(Ubuntu)上搭建MQTT服务器(EMQX )

目录 概述 1 认识EMQX 1.1 EMQX 简介 1.2 EMQX 版本类型 2 Ubuntu搭建EMQX 平台 2.1 下载和安装 2.1.1 下载 2.1.2 安装 2.2 查看运行端口 3 运行Dashboard 管理控制台 3.1 查看Ubuntu上的防火墙 3.2 运行Dashboard 管理控制台 概述 本文主要介绍EMQX 的一些内容&a…

【零基础学习05】嵌入式linux驱动中platform与设备树基本实现

大家好,为了进一步提升大家对实验的认识程度,每个控制实验将加入详细控制思路与流程,欢迎交流学习。 今天主要学习一下,基于总线、设备和驱动进行匹配的平台驱动模型,这次将采用设备树的platform设备与驱动的编写方法,目前绝大多数的Linux内核已经支持设备树,这次主要来…

西井科技参与IATA全球货运大会 以AI绿动能引领智慧空港新未来

3月12日至14日&#xff0c;由国际航空运输协会IATA主办的全球货运大会&#xff08;World Cargo Symposium&#xff09;在中国香港成功举办&#xff0c;这是全球航空货运领域最大规模与影响力的年度盛会。作为大物流领域全球领先的“智能化与新能源化”综合解决方案提供商&#…

05-ESP32-S3-IDF USART

ESP32-S3 IDF USART详解 USART简介 USART是一种串行通信协议&#xff0c;广泛应用于微控制器和计算机之间的通信。USART支持异步和同步模式&#xff0c;因此它可以在没有时钟信号的情况下&#xff08;异步模式&#xff09;或有时钟信号的情况下&#xff08;同步模式&#xff…

【STL】string各种函数的应用

1.string 基本赋值操作 string assign&#xff08;string str&#xff0c;int n&#xff09; string assign&#xff08;string str,int pos,int n&#xff09; 2.string存取字符操作 (at()) 注意&#xff1a;[ ]越界不会抛出异常&#xff0c;at越界会抛出异常 3.string拼接…

bpmn-js系列之Palette

前边写了四篇文章介绍了bpmn.js的基本使用&#xff0c;最近陆续有小伙伴加我催更&#xff0c;感谢对我这个半吊子前端的信任&#xff0c;接着更新bpmn.js的一些高级用法&#xff0c;本篇介绍对左侧工具栏Palette的隐藏和自定义修改 隐藏shape 左侧工具栏Palette有些图标我用不…

如何利用ChatGPT联系英语口语和听写!分享一些Prompt!

参考文章 ChatGPT4升级方法 namecheap购买方法 sora namecheap 支付 首先先看ChatGPT修改英语作文的能力 足以证明ChatGPT的能力 ChatGPT英语练习 口语&#xff1a; 实时交谈纠错发音纠错语句 写作&#xff1a; 写作建议构思文本 模拟考试&#xff1a; 雅思、托福和…

在域控的Users目录下批量创建用户组,名称来自Excel

对于CSV文件&#xff0c;PowerShell可以直接读取并处理&#xff0c;无需额外安装模块。假设你的CSV文件中&#xff0c;用户组名称在第一列&#xff0c;文件名为"groups.csv"&#xff0c;可以使用以下PowerShell脚本来批量创建&#xff1a; # 读取CSV文件中的数据 $g…

西门子PLCS7-1200位逻辑指令的使用

1.LAD触点 常开触点的位值为1时&#xff0c;常开触点将闭合&#xff08;ON&#xff09;。位值为0时&#xff0c;常开触点将闭合&#xff08;OFF&#xff09;。 常闭触点的位值为1时&#xff0c;常闭触点将闭合&#xff08;OFF&#xff09;。位值为0时&#xff0c;常闭触点将闭…

2024.3.13 C++

思维导图 设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 #include <iostream>using namespace…

HttpContext请求接收上下文模块设计与实现(http模块四)

目录 类功能 类定义 类实现 编译测试 类功能 类定义 // HttpContext接收请求上下文模块功能设计 typedef enum {RECV_HTTP_ERROR,RECV_HTTP_LINE,RECV_HTTP_HEAD,RECV_HTTP_BODY,RECV_HTTP_OVER } HttpRecvStatu;class HttpContext { private:int _resp_statu; …

【leetcode热题】寻找旋转排序数组中的最小值

已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2]若旋转 7 次&#xff0…

数据库基础知识超详细解析~‍(进阶/复习版)

文章目录 前言一、数据库的操作1.登入数据库2.创建数据库3.显示当前数据库4.使用数据库5.删除数据库 二、常用数据类型三、数据库的约束1约束类型2NULL约束3UNIQUE:唯一约束4DEFAULT&#xff1a;默认值约束5 PRIMARY KEY&#xff1a;主键约束6 FOREIGN KEY&#xff1a;外键约束…

Devin,第一位AI软件工程师

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

php 对接Bigo海外广告平台收益接口Reporting API

今天对接的是Bigo广告reporting api接口&#xff0c;拉取广告收益回来自己做统计。记录分享给大家 首先是文档地址,进入到BIGO后台就能看到文档地址以及参数&#xff1a; 文档地址&#xff1a;https://www.bigossp.com/guide/sdk/reportingApi/doc?type1 接入这些第三方广告…