当前位置: 首页 > news >正文

Spring cache整合Redis使用介绍

🍓 简介:java系列技术分享(👉持续更新中…🔥)
🍓 初衷:一起学习、一起进步、坚持不懈
🍓 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正🙏
🍓 希望这篇文章对你有所帮助,欢迎点赞 👍 收藏 ⭐留言 📝

🍓 更多文章请点击
在这里插入图片描述在这里插入图片描述

文章目录

  • 一、 Spring cache简介
  • 二、 常用注解
  • 三、 使用步骤
    • 3.1 引入依赖
    • 3.2 开启缓存支持
    • 3.3 引入Redis配置
    • 3.4 添加注解
    • 3.5 启动测试,发现报如下错误
    • 3.6 Redis客户端存储的是二进制数据如何解决
  • 四、 注解中key和value的介绍及使用(重点)
    • 4.1 每个注解的SPEL表达式支持有所区别
    • 4.2 使用时还需注意
  • 五、 设置Spring cache的缓存失效时间
    • 5.1 第一种
    • 5.2 第二种

是

一、 Spring cache简介

官方文档中有详细介绍:https://docs.spring.io/spring-framework/reference/integration/cache/annotations.html
Spring cache是Spring提供的通用缓存框架,利用AOP,实现了基于注解的缓存功能。
Spring cache只是提供了一层抽象,地城可以切换不同的cache实现,具体就是通过CacheManager接口开统一不同的缓存技术,CacheManagerSpring提供的各种缓存技术抽象接口。

二、 常用注解

注解描述
@EnableCaching开启缓存注解功能
@Cacheable 从缓存查询,存在则返回,不存在查询数据库,存入缓存
@CachePut将数据结果存入缓存
@CacheEvict清空缓存内容属性(allEntries = true) 表示清空所有
@Caching多缓存配置

缓存非null值
因为在使用中,可能会查询到null所以进行处理
在@Cacheable注解中,提供了两个属性,分别是 :condition ,unless

  • condition:表示满足条件,再缓存
  • unless: 表示满足条件,不缓存
  @Cacheable(value = "cache",key = "#id",unless = "#result == null")@GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) {return providerService.queryById(id);}

注意: 这里只能使用unless,因为在condition中无法获取到结果#result

三、 使用步骤

  • 在Spring Boot项目中,使用缓存技术只需在项目导入相关缓存技术的依赖包,并在启动类上使用@EnableCaching开启缓存支持。
  • 由于Spring cache的基本功能是spring核心(spring-context)中提供,无需引入其他依赖。
  • 默认情况下,Spring cache使用ConcurrentHashMap作为本地缓存存储数据,如何要使用其他的缓存框架,我们只需要做简单的配置即可。
  • 例如:使用Redis作为缓存技术,只需要导入Spring data Redis的maven坐标即可

3.1 引入依赖

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency>

3.2 开启缓存支持

@EnableCaching
@SpringBootApplication
public class ProviderApplication {public static void main(String[] args) {SpringApplication.run(ProviderApplication.class, args);}
}

3.3 引入Redis配置

默认情况下,Spring cache使用ConcurrentHashMap作为本地缓存存储数据,如何要使用其他的缓存框架,我们只需要做简单的配置即可。

 <!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
spring:redis:host: 196.120.168.100port: 6379database: 1password:

3.4 添加注解

下面方法只是根据id查询数据库,因此简单的代码就不展示了,我们主要关注注解的使用就可以了。

    /*** 根据id查询用户信息*/@Cacheable("user")@GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) {return providerService.queryById(id);}

3.5 启动测试,发现报如下错误

在这里插入图片描述
只需加入该配置即可:

spring:cache:type: redis

接口返回正常,redis客户端查看正常
在这里插入图片描述在这里插入图片描述

3.6 Redis客户端存储的是二进制数据如何解决

但是发现redis存储的格式是二进制形式(默认序列化使用的是 JdkSerializationRedisSerializer ,存储二进制字节码)。不够直观,这时我们可以自定义RedisTemplate模板

@Configuration
public class RedisConfig extends CachingConfigurerSupport {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);// 用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();redisTemplate.setKeySerializer(stringRedisSerializer); // keyJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper = new ObjectMapper();// 指定要序列化的域(field,get,set),访问修饰符(public,private,protected)objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(objectMapper);redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); //valueredisTemplate.setHashKeySerializer(stringRedisSerializer);redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();return redisTemplate;}
}
  • 再次调用查看,还是二进制,这时发现RedisTemplate调用是正常的,而只有使用@Cacheable("user")时是二进制
  • 这是因为使用@Cacheable注解的时候会将返回的对象缓存起来,默认缓存的值是二进制的,这时添加如下配置,定义redisCacheManagerredisTemplate配置进行绑定
  @Beanpublic RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
//                .entryTtl(Duration.ofHours(1))// 设置缓存有效期一小时.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);}

成功查看
在这里插入图片描述

四、 注解中key和value的介绍及使用(重点)

  • value:缓存的名称,每个缓存名称下面可以有多个key
  • key : 缓存的key, 支持SPEL表达式
    /*** 根据id查询用户信息*/@CachePut(value = "user",key = "#result.id")@GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) {return providerService.queryById(id);}

4.1 每个注解的SPEL表达式支持有所区别

官方文档中有详细介绍:https://docs.spring.io/spring-framework/reference/integration/cache/annotations.html
在这里插入图片描述这里列出一些,供参考
在这里插入图片描述在这里插入图片描述

常用格式@CachePut(value = "cache",key = "#user.id")@CachePut(value = "cache",key = "#p0.id")@CachePut(value = "cache",key = "#root.args[0].id")@CachePut(value = "cache",key = "#id")@CachePut(value = "cache",key = "'test'+ #id")静态方法调用@Cacheable(value = "user",key = "T(com.use.dto.bean.CurrentRequest).getUser().getUid()")

4.2 使用时还需注意

例如:

  • @CachePut可以使用#result
  • @Cacheable中则不可以使用,具体这里不一一测试,使用时还需注意

在这里插入图片描述
在这里插入图片描述

五、 设置Spring cache的缓存失效时间

在真实开发中失效时间是必须设置的,不然一直占用内存是不可取的

5.1 第一种

全局生效

spring:redis:time-to-live: 1800000  # 缓存过期时间 单位毫秒

5.2 第二种

局部设置

@Configuration
public class RedisCacheConfig {//设置失效时间private static final Map<String, Duration> cacheMap;static {cacheMap = ImmutableMap.<String, Duration>builder().put("user", Duration.ofMinutes(5)).build();}//配置RedisCacheManagerBuilderCustomizer对象@Beanpublic RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {return (builder) -> {//根据不同的cachename设置不同的失效时间for (Map.Entry<String, Duration> entry : cacheMap.entrySet()) {builder.withCacheConfiguration(entry.getKey(),RedisCacheConfiguration.defaultCacheConfig().entryTtl(entry.getValue()));}};}
}

在这里插入图片描述在这里插入图片描述

相关文章:

Spring cache整合Redis使用介绍

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…...

Metasploit提权

一、bypassuac 用户账户控制&#xff08;User Account Control&#xff0c;简写作UAC)是微软公司在其Windows Vista及更高版本操作系统中采用的一种控制机制。其原理是通知用户是否对应用程序使用硬盘驱动器和系统文件授权&#xff0c;以达到帮助阻止恶意程序&#xff08;有时也…...

TypeScript三种特殊类型

1.any类型 说明&#xff1a;any类型代表着可以赋值任意类型 let nickname:any"王二"nickname15nicknametruenicknameundefinednicknamenullnickname{}2.unknown类型 说明&#xff1a;类似any类型&#xff1b;只是不能赋值到其它类型上&#xff1b;除了any和known。…...

如何使用CSS实现一个响应式轮播图?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现响应式轮播图的示例⭐ HTML 结构⭐ CSS 样式 (styles.css)⭐ JavaScript 代码 (script.js)⭐ 实现说明⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带…...

数据生成 | MATLAB实现MCMC马尔科夫蒙特卡洛模拟的数据生成

数据生成 | MATLAB实现MCMC马尔科夫蒙特卡洛模拟的数据生成 目录 数据生成 | MATLAB实现MCMC马尔科夫蒙特卡洛模拟的数据生成生成效果基本描述模型描述程序设计参考资料 生成效果 基本描述 1.MATLAB实现MCMC马尔科夫蒙特卡洛模拟的数据生成&#xff1b; 2.马尔科夫链蒙特卡洛方…...

【从零开始的rust web开发之路 二】axum中间件和共享状态使用

系列文章目录 第一章 axum学习使用 第二章 axum中间件使用 文章目录 系列文章目录前言一、中间件是什么二、中间件使用常用中间件使用中间件使用TraceLayer中间件实现请求日志打印自定义中间件 共享状态 前言 上篇文件讲了路由和参数相应相关的。axum还有个关键的地方是中间件…...

Vue操作时间

一、获取现在时间 const currentTime () > {let date new Date();let year date.getFullYear(); //月份从0~11&#xff0c;所以加一let month date.getMonth();let dateArr [date.getMonth() 1,date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),…...

数据库——Redis 常见数据结构以及使用场景分析

文章目录 1. string2. list3. hash4. set5. sorted set 你可以自己本机安装 redis 或者通过 redis 官网提供的在线 redis 环境。 1. string 介绍 &#xff1a;string 数据结构是简单的 key-value 类型。虽然 Redis 是用 C 语言写的&#xff0c;但是 Redis 并没有使用 C 的字符串…...

数学建模-规划工具箱yalmip

官网下载 实例 %% yalmip 求解 yalmip clc;clear;close all; %% %sdpvar实型变量 intvar 整形变量 binvar 0-1型变量 psdpvar(3,1); %定义变量 %目标函数 要把求最大值转化为最小值 Objective-p(1)^2p(2)^2-p(2)*p(3);%约束条件 Constraints[0<p<1,(p(1)^2p…...

[SQL挖掘机] - 窗口函数 - 计算移动平均

介绍: 在窗口函数使用时&#xff0c;计算的是累积到当前行的所有的数据的相关操作。 实际上&#xff0c;还可以指定更加详细的汇总范围。该汇总范围称为 框架 (frame)。 其实这里也可以理解成一个窗口, 这个窗口是我们可以进行设置的. 之前我们介绍的窗口函数是根据partition…...

域名和hostname

最近用git克隆远程仓库时总是超时&#xff0c;报错说是代理的问题&#xff0c;但打开和关闭代理都没能解决问题&#xff0c;后面了解到可以关闭git命令的全局代理&#xff1a; git config --global --unset http.proxy git config --global --unset https.proxy如果下次要用的…...

echarts 甘特图一组显示多组数据

<template><el-button type"primary" click"addlin">添加线</el-button><el-button type"success" click"addArea">添加区域</el-button><div ref"echart" id"echart" class&qu…...

1139. 最大的以 1 为边界的正方形;2087. 网格图中机器人回家的最小代价;1145. 二叉树着色游戏

1139. 最大的以 1 为边界的正方形 核心思想&#xff1a;枚举正方向的右下角坐标&#xff08;i&#xff0c;j&#xff09;&#xff0c;然后你只需要判断四条边的连续一的最小个数即可&#xff0c;这里是边求连续一的个数同时求解结果。 087. 网格图中机器人回家的最小代价 核心…...

css滚动条的使用

前言&#xff1a; css滚动条的使用。 1、使用案例1&#xff1a;背景不要&#xff0c;只展示一个滚动条 如果是默认整体&#xff0c;::就够用了&#xff0c;如果是某个元素&#xff0c;可以 .abc:: ,如果是scss这种的 &:: ::-webkit-scrollbar {width: 6px; } ::-webkit…...

优化Python代理爬虫的应用

当我们在资源受限的环境中使用Python代理爬虫时&#xff0c;我们需要采取一些优化措施&#xff0c;以确保程序的高效性和稳定性。在本文中&#xff0c;我将分享一些关于如何优化Python代理爬虫在资源受限环境下的应用的实用技巧。 首先我们来了解&#xff0c;哪些情况算是资源…...

[C++] STL_vector使用与常用接口的模拟实现

文章目录 1、vector的介绍2、vector的使用2.1 vector的定义2.2 vector迭代器的使用2.3 vector的空间增长问题 3、vector的增删查改3.1 push_back&#xff08;重点&#xff09;3.2 pop_back&#xff08;重点&#xff09;3.3 operator[]&#xff08;重点&#xff09;3.4 insert3.…...

【LeetCode】167. 两数之和 II - 输入有序数组 - 双指针

目录标题 2023-8-23 09:25:08 2023-8-23 09:25:08 自己写的不是常量级的额外空间&#xff0c;但是写出来了&#xff0c;记录一下。 下次写的时候&#xff0c;请用双指针。 &#xff08;其实我想了想一想&#xff0c;双指针就没感觉出来&#xff1a;因为我只想到双指针两个都…...

YOLOV1

YOU ONLY LOOK ONCE...

美团增量数仓建设新进展

摘要&#xff1a;本文整理自美团系统研发工程师汤楚熙&#xff0c;在 Flink Forward Asia 2022 实时湖仓专场的分享。本篇内容主要分为四个部分&#xff1a; 建设背景核心能力设计与优化业务实践未来展望 点击查看原文视频 & 演讲PPT 一、美团增量数仓的建设背景 美团数仓架…...

​LeetCode解法汇总2337. 移动片段得到字符串

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你两个字…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...