【Spring Boot 3】【Redis】基本数据类型操作

【Spring Boot 3】【Redis】基本数据类型操作

  • 背景
  • 介绍
  • 开发环境
  • 开发步骤及源码
  • 工程目录结构

背景

软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的时间、检索不止一篇资料才能得出一个可工作的DEMO,这占用了我大量的时间精力。因此本文旨在通过一篇文章即能还原出可工作的、甚至可用于生产的DEMO,期望初学者能尽快地迈过0到1的这一步骤,并在此基础上不断深化对相关知识的理解。
为达以上目的,本文会将开发环境、工程目录结构、开发步骤及源码尽量全面地展现出来,文字描述能简则简,能用代码注释的绝不在正文中再啰嗦一遍,正文仅对必要且关键的信息做重点描述。

介绍

本文介绍开发Spring Boot应用时借助Spring Data Redis实现对Redis五种基本数据(字符串string、哈希hash、列表list、集合set、有序集合zset)类型的操作。

开发环境

分类名称版本
操作系统WindowsWindows 11
JDKOracle JDK21.0.1
IDEIntelliJ IDEA2023.2.4
构建工具Apache Maven3.9.3
缓存Redis7.2

开发步骤及源码

1> 创建Maven工程,添加依赖。

    <properties><spring-boot.version>3.2.1</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>${spring-boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${spring-boot.version}</version><scope>test</scope></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.3</version></dependency></dependencies>

2> 添加应用配置(src/main/resources/application.yml)。

spring:data:redis:# 连接地址host: 127.0.0.1# 端口port: 6379# Redis数据库索引,默认为 0database: 0# 用户名(可选)# username:# 密码(可选)# password:

3> 定义SpringBoot应用启动类。

package com.jiyongliang.springboot;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBoot3RedisDataApplication {public static void main(String[] args) {SpringApplication.run(SpringBoot3RedisDataApplication.class, args);}
}

4> 字符串(string)

package com.jiyongliang.springboot;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;@SpringBootTest
class RedisStringTests {@AutowiredRedisTemplate<String, Object> redisTemplate;String key = "string-key";@AfterEachvoid afterEach() {redisTemplate.delete(key);}@Testvoid testString() {// 添加字符串缓存数据redisTemplate.opsForValue().set(key, "string data");// 获取字符串缓存数据String cachedString = (String) redisTemplate.opsForValue().get(key);Assertions.assertThat(cachedString).isNotNull().isEqualTo("string data");}
}

5> 哈希(hash)

package com.jiyongliang.springboot;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import java.util.HashMap;
import java.util.Map;@SpringBootTest
class RedisHashTests {@AutowiredRedisTemplate<String, Object> redisTemplate;String key = "hash-single-key";@BeforeEachvoid beforeEach() {redisTemplate.delete(key);}@Testvoid testHash() {// 添加单个Hash缓存数据redisTemplate.opsForHash().put(key, "hash key", "hash value");// 获取单个Hash缓存数据String cachedHash = (String) redisTemplate.opsForHash().get(key, "hash key");Assertions.assertThat(cachedHash).isEqualTo("hash value");redisTemplate.delete(key);// 添加map缓存数据Map<String, String> map = new HashMap<>();map.put("map-key-1", "map value 1");map.put("map-key-2", "map value 2");map.put("map-key-3", "map value 3");redisTemplate.opsForHash().putAll(key, map);// 获取map缓存数据Map<Object, Object> cachedHashMap = redisTemplate.opsForHash().entries(key);Assertions.assertThat(cachedHashMap).isNotNull().containsEntry("map-key-1", "map value 1").containsEntry("map-key-2", "map value 2").containsEntry("map-key-3", "map value 3");}
}

6> 列表(list)

package com.jiyongliang.springboot;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import java.util.List;@SpringBootTest
class RedisListTests {@AutowiredRedisTemplate<String, Object> redisTemplate;String key = "list-key";@BeforeEachvoid beforeEach() {redisTemplate.delete(key);}@Testvoid testList() {// 添加List缓存数据redisTemplate.opsForList().leftPush(key, "list value 3");redisTemplate.opsForList().leftPush(key, "list value 2");redisTemplate.opsForList().leftPush(key, "list value 1");redisTemplate.opsForList().rightPush(key, "list value 4");redisTemplate.opsForList().rightPush(key, "list value 5");// 获取全部List缓存数据List<Object> cachedList = redisTemplate.opsForList().range(key, 0, -1);Assertions.assertThat(cachedList).isNotNull().isNotEmpty().hasToString("[list value 1, list value 2, list value 3, list value 4, list value 5]");// 获取指定下标数据String listValue = (String) redisTemplate.opsForList().index(key, 2);Assertions.assertThat(listValue).isEqualTo("list value 3");listValue = (String) redisTemplate.opsForList().index(key, 5);Assertions.assertThat(listValue).isNull();// 从左边开始取数据listValue = (String) redisTemplate.opsForList().leftPop(key);Assertions.assertThat(listValue).isEqualTo("list value 1");// 从右边开始取数据listValue = (String) redisTemplate.opsForList().rightPop(key);Assertions.assertThat(listValue).isEqualTo("list value 5");// 获取list长度Long length = redisTemplate.opsForList().size(key);Assertions.assertThat(length).isNotNull().isEqualTo(3);Assertions.assertThat(redisTemplate.opsForList().range(key, 0, -1)).isNotNull().isNotEmpty().hasToString("[list value 2, list value 3, list value 4]");}
}

7> 集合(set)

package com.jiyongliang.springboot;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;@SpringBootTest
class RedisSetTests {@AutowiredRedisTemplate<String, Object> redisTemplate;String key1 = "set-key-1";String key2 = "set-key-2";@BeforeEachvoid beforeEach() {redisTemplate.delete(key1);redisTemplate.delete(key2);}@Testvoid testSet() {// 添加Set缓存数据String[] setData = new String[]{"A", "B", "C", "D", "D", "C", "D", "E", "F", "F", "G"};Long addCount = redisTemplate.opsForSet().add(key1, setData);Set<String> expected = Arrays.stream(setData).collect(Collectors.toSet());Assertions.assertThat(addCount).isNotNull().isEqualTo(expected.size());// 获取Set缓存数据Set<Object> cachedSet = redisTemplate.opsForSet().members(key1);Assertions.assertThat(cachedSet).isNotNull().hasSameSizeAs(expected).containsAll(expected);// 判断是否在Set缓存数据中Assertions.assertThat(redisTemplate.opsForSet().isMember(key1, "F")).isTrue();Assertions.assertThat(redisTemplate.opsForSet().isMember(key1, "X")).isFalse();// 返回缓存Set的并集String[] setTempData = new String[]{"A", "X", "E", "Y", "G", "Z"};redisTemplate.opsForSet().add(key2, setTempData);Set<Object> unionSet = redisTemplate.opsForSet().union(key1, key2);Assertions.assertThat(unionSet).isNotNull().hasSize(expected.size() + 3).containsAll(expected).containsAll(Set.of("X", "Y", "Z"));// 返回缓存Set的交集Set<Object> intersectSet = redisTemplate.opsForSet().intersect(key1, key2);Assertions.assertThat(intersectSet).isNotNull().hasSize(3).containsAll(Set.of("A", "E", "G"));// 返回缓存的set-key-1中存在但set-key-2中不存在的数据Set<Object> differenceSet = redisTemplate.opsForSet().difference(key1, key2);Assertions.assertThat(differenceSet).isNotNull().hasSize(expected.size() - 3).containsAll(Set.of("B", "C", "D", "F"));}
}

8> 有序集合(zset)

package com.jiyongliang.springboot;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import java.util.Set;@SpringBootTest
class RedisZSetTests {@AutowiredRedisTemplate<String, Object> redisTemplate;String key = "zset-key";@BeforeEachvoid beforeEach() {redisTemplate.delete(key);}@Testvoid testZSet() {// 添加ZSet缓存数据redisTemplate.opsForZSet().add(key, "X", 1);redisTemplate.opsForZSet().add(key, "Y", 2);redisTemplate.opsForZSet().add(key, "Z", 3);// 值相同的情况下,权重会被覆盖redisTemplate.opsForZSet().add(key, "X", 1);redisTemplate.opsForZSet().add(key, "Y", 3);redisTemplate.opsForZSet().add(key, "Z", 5);// 获取ZSet缓存数据Set<Object> cachedZSet = redisTemplate.opsForZSet().range(key, 0, -1);Assertions.assertThat(cachedZSet).isNotNull().hasSize(3).containsAll(Set.of("X", "Y", "Z"));// 获取值对应的权重Double score = redisTemplate.opsForZSet().score(key, "Y");Assertions.assertThat(score).isNotNull().isEqualTo(3);// 获取值对应的排名(从0开始)Long rank = redisTemplate.opsForZSet().rank(key, "Y");Assertions.assertThat(rank).isNotNull().isEqualTo(1);// 根据score范围获取值Set<Object> rangedZSet = redisTemplate.opsForZSet().rangeByScore(key, 1, 4);Assertions.assertThat(rangedZSet).isNotNull().hasSize(2).containsAll(Set.of("X", "Y"));}
}

9> 数据过期

package com.jiyongliang.springboot;import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;import java.util.concurrent.TimeUnit;@SpringBootTest
class RedisExpireTests {@AutowiredRedisTemplate<String, Object> redisTemplate;String key = "expire-key";@BeforeEachvoid beforeEach() {redisTemplate.delete(key);}@Testvoid testExpire() throws InterruptedException {redisTemplate.opsForValue().set(key, "expire data");Assertions.assertThat(redisTemplate.opsForValue().get(key)).isNotNull().isEqualTo("expire data");redisTemplate.opsForValue().getOperations().expire(key, 3, TimeUnit.SECONDS);TimeUnit.SECONDS.sleep(3);Assertions.assertThat(redisTemplate.opsForValue().get(key)).isNull();}
}

10> 单元测试结果
单元测试结果

工程目录结构

工程目录结构

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

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

相关文章

http网络编程——在ue5中实现文件传输功能

http网络编程在ue5中实现 需求&#xff1a;在unreal中实现下载功能&#xff0c;输入相关url网址&#xff0c;本地文件夹存入相应文件。 一、代码示例 1.Build.cs需要新增Http模块&#xff0c;样例如下。 PublicDependencyModuleNames.AddRange(new string[] { "Core&q…

【2023 CCF 大数据与计算智能大赛】基于TPU平台实现超分辨率重建模型部署 基于Real-ESRGAN的TPU超分模型部署

2023 CCF 大数据与计算智能大赛 《基于TPU平台实现超分辨率重建模型部署》 洋洋很棒 李鹏飞 算法工程师 中国-烟台 2155477673qq.com 团队简介 本人从事工业、互联网场景传统图像算法及深度学习算法开发、部署工作。其中端侧算法开发及部署工作5年时间。 摘要 本文是…

基于java+Springboot操作系统教学交流平台详细设计实现

基于javaSpringboot操作系统教学交流平台详细设计实现 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统…

C++ 知识列表【图】

举例C的设计模式和智能指针 当谈到 C 的设计模式时&#xff0c;以下是一些常见的设计模式&#xff1a; 工厂模式&#xff08;Factory Pattern&#xff09;&#xff1a;用于创建对象的模式&#xff0c;隐藏了对象的具体实现细节&#xff0c;只暴露一个公共接口来创建对象。 单例…

C++从小白到初级工程师【个人学习笔记】

目录 1.背景2.基础二维数组概念二维数组定义方式 二维数组数组名称概念例子 函数的分文件编写概念示例 指针指针的基本概念指针变量的定义和使用 空指针和野指针空指针实例野指针实例 const修饰指针概念const修饰指针 --- 常量指针 指针和数组作用示例 指针和函数作用示例 指针…

docker compose安装milvus

下载对应版本的milvus-standalone-docker-compose.yml wget https://github.com/milvus-io/milvus/releases/download/v2.3.5/milvus-standalone-docker-compose.yml重新命令为docker-compose.yml mv milvus-standalone-docker-compose.yml docker-compose.yml启动milvus doc…

sqlmap使用教程(2)-连接目标

目录 连接目标 1.1 设置认证信息 1.2 配置代理 1.3 Tor匿名网络 1.4 检测WAF/IPS 1.5 调整连接选项 1.6 处理连接错误 连接目标 场景1&#xff1a;通过代理网络上网&#xff0c;需要进行相应配置才可以成功访问目标主机 场景2&#xff1a;目标网站需要进行身份认证后才…

VSCode Python Windows环境下创建虚拟环境,隔离每个项目的依赖pip包,推荐使用!

VSCode Python Windows环境下创建虚拟环境 Visual Studio Code 可以隔离不同项目的pip依赖包&#xff0c;防止不同版本的干扰**&#xff08;推荐使用&#xff09;** 先在python官网https://www.python.org/downloads/下载需要的python版本&#xff08;我选择了3.9.8&#xff09…

JavaScript中的BigInt类型

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 在我们日常生活中&#xff0c;JavaScript已经成为了一种无处不在的编…

基于SWAT-MODFLOW地表水与地下水耦合

详情点击链接&#xff1a;基于SWAT-MODFLOW地表水与地下水耦合 第一模型原理与层次结构 1.1 SWAT模型 1.2 MODFLOW模型 1.3 SWAT-MODFLOW地表-地下耦合模型 1.4 QSWATMOD功能与层次结构 1.5 模型实现所需软件平台 第二QGIS软件 2.1 QGIS平台 2.2 QGIS安装 2.3 QGIS界面…

Oracle 高级网络压缩 白皮书

英文版白皮书在这里 或 这里。 本文包括了对英文白皮书的翻译&#xff0c;和我觉得较重要的要点总结。 执行概述 Oracle Database 12 引入了一项新功能&#xff1a;高级网络压缩&#xff0c;作为高级压缩选项的一部分。 本文概述了高级网络压缩、其优点、配置细节和性能分析…

深入HashMap底层理解阿里手册的遍历守则

写在文章开头 你好&#xff0c;我叫sharkchili&#xff0c;目前还是在一线奋斗的Java开发&#xff0c;经历过很多有意思的项目&#xff0c;也写过很多有意思的文章&#xff0c;是CSDN Java领域的博客专家&#xff0c;也是Java Guide的维护者之一&#xff0c;非常欢迎你关注我的…

特斯拉FSD的神经网络(Tesla 2022 AI Day)

这是特斯拉的全自动驾驶&#xff08;Full Self Driver&#xff09;技术结构图&#xff0c;图中把自动驾驶模型拆分出分成了几个依赖的模块&#xff1a; 技术底座&#xff1a;自动标注技术处理大量数据&#xff0c;仿真技术创造图片数据&#xff0c;大数据引擎进不断地更新&…

Visual Studio2022实用使用技巧集

前言 对于.NET开发者而言Visual Studio是我们日常工作中比较常用的开发工具&#xff0c;掌握一些Visual Studio实用的搜索、查找、替换技巧可以帮助我们大大提高工作效率从而避免996。 Visual Studio更多实用技巧 https://github.com/YSGStudyHards/DotNetGuide 代码和功能搜…

用flinkcdc debezium来捕获数据库的删除内容

我在用flinkcdc把数据从sqlserver写到doris 正常情况下sqlserver有删除数据&#xff0c;doris是能捕获到并很快同步删除的。 但是我现在情况是doris做为数仓&#xff0c;数据写到ods&#xff0c;ods的数据还会通过flink计算后写入dwd层&#xff0c;所以此时ods的数据是删除了…

【解决方案】浅谈安科瑞无线测温监控系统方案

1概述 Acrel-2000T无线测温监控系统装置适用于高低压开关柜内电缆接头、断路器触头、刀闸开关、高压电缆中间头、干式变压器、低压大电流等设备的温度监测&#xff0c;防止在运行过程中因氧化、松动、灰尘等因素造成接点接触电阻过大而发热成为安全隐患&#xff0c;提高设备安…

用ChatGPT教学、科研!亚利桑那州立大学与OpenAI合作

亚利桑那州立大学&#xff08;简称“ASU”&#xff09;在官网宣布与OpenAI达成技术合作。从2024年2月份开始&#xff0c;为所有学生提供ChatGPT企业版访问权限&#xff0c;主要用于学习、课程作业和学术研究等。 为了帮助学生更好地学习ChatGPT和大语言模型产品&#xff0c;AS…

3DMAX初级小白班第一课:菜单栏介绍

基本介绍 这里不可能一个一个选项全部教给大家&#xff08;毕竟之后靠实操慢慢就记住了&#xff09;&#xff0c;只说一些相对需要注意的设置。 自定义-热键编辑器-热键设置 这里有你所需要的全部快捷键 自定义-自定义UI启动布局 将UI布局还原到启动的位置 自定义-通用单…

第2章-OSI参考模型与TCP/IP模型

目录 1. 引入 2. OSI参考模型 2.1. 物理层 2.2. 数据链路层 2.3. 网络层 2.4. 传输层 2.5. 会话层 2.6. 表示层 2.7. 应用层 3. 数据的封装与解封装 4. TCP/IP模型 4.1. 背景引入 4.2. TCP/IP模型&#xff08;4层&#xff09; 4.3. 拓展 1. 引入 1&#xff09;产…

Maven 打包时,依赖配置正确,但是类引入出现错误,一般是快照(Snapshot)依赖拉取策略问题

问题描述&#xff1a; 项目打包时&#xff0c;类缺少依赖&#xff0c;操作 pom.xml -> Maven -> Reload project &#xff0c;还是不生效&#xff0c;但是同事&#xff08;别人&#xff09;那里正常。 问题出现的环境&#xff1a; 可能项目是多模块项目&#xff0c;结构…