从0开始搭建一个生产级SpringBoot2.0.X项目(八)SpringBoot 使用Redis
前言
最近有个想法想整理一个内容比较完整springboot项目初始化Demo。
SpringBoot使用Redis 缓存数据
一、 pom引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.0.1-jre</version></dependency>
二、 application-dev.yaml 增加redis 连接配置
spring:datasource:driver-class-name: oracle.jdbc.OracleDriverurl: jdbc:oracle:thin:@//127.0.0.1:1521/orcl2username: murg_demopassword: 654321hikari:connection-test-query: SELECT 1 FROM DUALminimum-idle: 10maximum-pool-size: 50idle-timeout: 1200000max-lifetime: 1800000connection-timeout: 180000cache:redis:time-to-live: 1800sredis:host: 127.0.0.1port: 6379password: adminlogging:level:org.springframework.security: debug
三、创建RedisConfig类,规定序列化格式
package com.murg.bootdemo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {//redisTemplate注入到Spring容器@Beanpublic RedisTemplate<String,String> redisTemplate(RedisConnectionFactory factory){RedisTemplate<String,String> redisTemplate=new RedisTemplate<>();//自定义序列化方式使用String序列化:可以简化操作并提高查找效率。RedisSerializer<String> redisSerializer = new StringRedisSerializer();redisTemplate.setConnectionFactory(factory);//key序列化redisTemplate.setKeySerializer(redisSerializer);//value序列化redisTemplate.setValueSerializer(redisSerializer);//value hashmap序列化redisTemplate.setHashKeySerializer(redisSerializer);//key hashmap序列化redisTemplate.setHashValueSerializer(redisSerializer);return redisTemplate;}
}
四、创建RedisUtils 工具类
package com.murg.bootdemo.util;import com.google.common.collect.HashMultimap;
import org.springframework.context.annotation.Bean;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;/*** @description: Redis工具类*/
@Component
public class RedisUtils {private static StringRedisTemplate redisTemplate;public RedisUtils(StringRedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}/*** 写入缓存** @param key redis键* @param value redis值* @return 是否成功*/public static boolean set(final String key, String value) {boolean result = false;try {ValueOperations<String, String> operations = redisTemplate.opsForValue();operations.set(key, value);result = true;} catch (Exception e) {e.printStackTrace();}return result;}/*** 写入缓存设置时效时间** @param key redis键* @param value redis值* @return 是否成功*/public static boolean set(final String key, String value, Long expireTime) {boolean result = false;try {ValueOperations<String, String> operations = redisTemplate.opsForValue();operations.set(key, value);redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);result = true;} catch (Exception e) {e.printStackTrace();}return result;}/*** 批量删除对应的键值对** @param keys Redis键名数组*/public static void removeByKeys(final String... keys) {for (String key : keys) {remove(key);}}/*** 批量删除Redis key** @param pattern 键名包含字符串(如:myKey*)*/public static void removePattern(final String pattern) {Set<String> keys = redisTemplate.keys(pattern);if (keys != null && keys.size() > 0)redisTemplate.delete(keys);}/*** 删除key,也删除对应的value** @param key Redis键名*/public static void remove(final String key) {if (exists(key)) {redisTemplate.delete(key);}}/*** 判断缓存中是否有对应的value** @param key Redis键名* @return 是否存在*/public static Boolean exists(final String key) {return redisTemplate.hasKey(key);}/*** 读取缓存** @param key Redis键名* @return 是否存在*/public static String get(final String key) {String result = null;ValueOperations<String, String> operations = redisTemplate.opsForValue();result = operations.get(key);return result;}/*** 哈希 添加** @param key Redis键* @param hashKey 哈希键* @param value 哈希值*/public static void hmSet(String key, String hashKey, String value) {HashOperations<String, String, String> hash = redisTemplate.opsForHash();hash.put(key, hashKey, value);}/*** 哈希获取数据** @param key Redis键* @param hashKey 哈希键* @return 哈希值*/public static String hmGet(String key, String hashKey) {HashOperations<String, String, String> hash = redisTemplate.opsForHash();return hash.get(key, hashKey);}/*** 判断hash是否存在键** @param key Redis键* @param hashKey 哈希键* @return 是否存在*/public static boolean hmHasKey(String key, String hashKey) {HashOperations<String, String, String> hash = redisTemplate.opsForHash();return hash.hasKey(key, hashKey);}/*** 删除hash中一条或多条数据** @param key Redis键* @param hashKeys 哈希键名数组* @return 删除数量*/public static long hmRemove(String key, String... hashKeys) {HashOperations<String, String, String> hash = redisTemplate.opsForHash();return hash.delete(key, hashKeys);}/*** 获取所有哈希键值对** @param key Redis键名* @return 哈希Map*/public static Map<String, String> hashMapGet(String key) {HashOperations<String, String, String> hash = redisTemplate.opsForHash();return hash.entries(key);}/*** 保存Map到哈希** @param key Redis键名* @param map 哈希Map*/public static void hashMapSet(String key, Map<String, String> map) {HashOperations<String, String, String> hash = redisTemplate.opsForHash();hash.putAll(key, map);}/*** 列表-追加值** @param key Redis键名* @param value 列表值*/public static void lPush(String key, String value) {ListOperations<String, String> list = redisTemplate.opsForList();list.leftPush(key, value);}/*** 列表-删除值** @param key Redis键名* @param value 列表值*/public static void lRemove(String key, String value) {ListOperations<String, String> list = redisTemplate.opsForList();list.remove(key, 0, value);}/*** 列表-获取指定范围数据** @param key Redis键名* @param start 开始行号(start:0,end:-1查询所有值)* @param end 结束行号* @return 列表*/public static List<String> lRange(String key, long start, long end) {ListOperations<String, String> list = redisTemplate.opsForList();return list.range(key, start, end);}/*** 集合添加** @param key Redis键名* @param value 值*/public static void add(String key, String value) {SetOperations<String, String> set = redisTemplate.opsForSet();set.add(key, value);}/*** 集合获取** @param key Redis键名* @return 集合*/public static Set<String> setMembers(String key) {SetOperations<String, String> set = redisTemplate.opsForSet();return set.members(key);}/*** 有序集合添加** @param key Redis键名* @param value 值* @param score 排序号*/public static void zAdd(String key, String value, double score) {ZSetOperations<String, String> zSet = redisTemplate.opsForZSet();zSet.add(key, value, score);}/*** 有序集合-获取指定范围** @param key Redis键* @param startScore 开始序号* @param endScore 结束序号* @return 集合*/public static Set<String> rangeByScore(String key, double startScore, double endScore) {ZSetOperations<String, String> zset = redisTemplate.opsForZSet();return zset.rangeByScore(key, startScore, endScore);}/*** 模糊查询Redis键名** @param pattern 键名包含字符串(如:myKey*)* @return 集合*/public static Set<String> keys(String pattern) {return redisTemplate.keys(pattern);}/*** 获取多个hashMap** @param keySet* @return List<Map < String, String>> hashMap列表*/public static List hashMapList(Collection<String> keySet) {return redisTemplate.executePipelined(new SessionCallback<String>() {@Overridepublic <K, V> String execute(RedisOperations<K, V> operations) throws DataAccessException {HashOperations hashOperations = operations.opsForHash();for (String key : keySet) {hashOperations.entries(key);}return null;}});}/*** 保存多个哈希表(HashMap)(Redis键名可重复)** @param batchMap Map<Redis键名,Map<键,值>>*/public static void batchHashMapSet(HashMultimap<String, Map<String, String>> batchMap) {// 设置5秒超时时间redisTemplate.expire("max", 25, TimeUnit.SECONDS);redisTemplate.executePipelined(new RedisCallback<List<Map<String, String>>>() {@Overridepublic List<Map<String, String>> doInRedis(RedisConnection connection) throws DataAccessException {Iterator<Map.Entry<String, Map<String, String>>> iterator = batchMap.entries().iterator();while (iterator.hasNext()) {Map.Entry<String, Map<String, String>> hash = iterator.next();// 哈希名,即表名byte[] hashName = redisTemplate.getStringSerializer().serialize(hash.getKey());Map<String, String> hashValues = hash.getValue();Iterator<Map.Entry<String, String>> it = hashValues.entrySet().iterator();// 将元素序列化后缓存,即表的多条哈希记录Map<byte[], byte[]> hashes = new HashMap<byte[], byte[]>();while (it.hasNext()) {// hash中一条key-value记录Map.Entry<String, String> entry = it.next();byte[] key = redisTemplate.getStringSerializer().serialize(entry.getKey());byte[] value = redisTemplate.getStringSerializer().serialize(entry.getValue());hashes.put(key, value);}// 批量保存connection.hMSet(hashName, hashes);}return null;}});}/*** 保存多个哈希表(HashMap)(Redis键名不可以重复)** @param dataMap Map<Redis键名,Map<哈希键,哈希值>>*/public static void batchHashMapSet(Map<String, Map<String, String>> dataMap) {// 设置5秒超时时间redisTemplate.expire("max", 25, TimeUnit.SECONDS);redisTemplate.executePipelined(new RedisCallback<List<Map<String, String>>>() {@Overridepublic List<Map<String, String>> doInRedis(RedisConnection connection) throws DataAccessException {Iterator<Map.Entry<String, Map<String, String>>> iterator = dataMap.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<String, Map<String, String>> hash = iterator.next();// 哈希名,即表名byte[] hashName = redisTemplate.getStringSerializer().serialize(hash.getKey());Map<String, String> hashValues = hash.getValue();Iterator<Map.Entry<String, String>> it = hashValues.entrySet().iterator();// 将元素序列化后缓存,即表的多条哈希记录Map<byte[], byte[]> hashes = new HashMap<byte[], byte[]>();while (it.hasNext()) {// hash中一条key-value记录Map.Entry<String, String> entry = it.next();byte[] key = redisTemplate.getStringSerializer().serialize(entry.getKey());byte[] value = redisTemplate.getStringSerializer().serialize(entry.getValue());hashes.put(key, value);}// 批量保存connection.hMSet(hashName, hashes);}return null;}});}/*** 保存多个哈希表(HashMap)列表(哈希map的Redis键名不能重复)** @param list Map<Redis键名,Map<哈希键,哈希值>>* @see RedisUtils*.batchHashMapSet()**/public static void batchHashMapListSet(List<Map<String, Map<String, String>>> list) {// 设置5秒超时时间redisTemplate.expire("max", 25, TimeUnit.SECONDS);redisTemplate.executePipelined(new RedisCallback<List<Map<String, String>>>() {@Overridepublic List<Map<String, String>> doInRedis(RedisConnection connection) throws DataAccessException {for (Map<String, Map<String, String>> dataMap : list) {Iterator<Map.Entry<String, Map<String, String>>> iterator = dataMap.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<String, Map<String, String>> hash = iterator.next();// 哈希名,即表名byte[] hashName = redisTemplate.getStringSerializer().serialize(hash.getKey());Map<String, String> hashValues = hash.getValue();Iterator<Map.Entry<String, String>> it = hashValues.entrySet().iterator();// 将元素序列化后缓存,即表的多条哈希记录Map<byte[], byte[]> hashes = new HashMap<byte[], byte[]>();while (it.hasNext()) {// hash中一条key-value记录Map.Entry<String, String> entry = it.next();byte[] key = redisTemplate.getStringSerializer().serialize(entry.getKey());byte[] value = redisTemplate.getStringSerializer().serialize(entry.getValue());hashes.put(key, value);}// 批量保存connection.hMSet(hashName, hashes);}}return null;}});}}
五、创建接口测试
TestRestController增加接口/testredis
@RequestMapping(value = "/testredis", method = RequestMethod.GET)public WebResult testRedis() {RedisUtils.set("test","aaaaa");return WebResult.ok(RedisUtils.get("test"));}

相关文章:
从0开始搭建一个生产级SpringBoot2.0.X项目(八)SpringBoot 使用Redis
前言 最近有个想法想整理一个内容比较完整springboot项目初始化Demo。 SpringBoot使用Redis 缓存数据 一、 pom引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>&…...
Ubuntu20.04两种安装及配置中文界面、输入法、换源、共享文件夹实现,及注意事项
虚拟机安装法 1、新建虚拟机,自定义下一步 任意指定路径 提高处理器数量能加快系统响应 完成以后不要运行,添加镜像文件 导入镜像文件,点击浏览 选择后打开->确认->运行虚拟机 出现这种情况就需要检查虚拟机的配置,操作系统…...
后端Java学习:springboot之文件上传(阿里云OSS存储)
一、什么是阿里云存储? 阿里云对象存储OSS(Object Storage Service),是一款海量、安全、低成本、高可靠的云存储服务。使用OSS,您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。 二、阿里云…...
python通过lunarcalendar库使用农历日期
农历日期库 介绍 lunarcalendar是一个处理农历日期的库 可以简单通过pip安装:pip install lunarcalendar lunarcalendar的github地址 从公历转为农历 from lunarcalendar import Converter, Solarsolar Solar(2024, 11, 1) lunar Converter.Solar2Lunar(sola…...
MySQL高级--范式与反范式
MySQL高级–范式与反范式 1. 背景 首先让我们来简单了解什么是范式与反范式 如下有部门表(包含:雇员、部门、部门领导) EMPLOYEEDEPARTMENTHEADJonesAccountingJonesSmithEngineeringSmithBrownAccountingJonesGreenEngineeringSmith 我们…...
实验05多重循环---7-02 打印矩形图案
打印一个 m 行 n 列的字符 * 组成的矩形图案。 输入格式: 输入在一行中给出空格隔开的两个整数,分别表示行数 m 和列数 n,其中 m 和 n 分别满足 1≤m≤10,1≤n≤20。 输出格式: 由字符 * 组成的 m 行 n 列的矩形图案。 输入样例: 3 5 输出…...
明源地产ERP WFWebService.asmx 反序列化RCE漏洞复现
0x01 产品简介 明源地产ERP是一款专为房地产行业设计的企业资源规划(ERP)系统,系统集成了项目管理、财务管理、客户关系管理、营销管理等多个模块,旨在帮助房地产企业提升运营效率、降低成本和提高客户满意度。它充分考虑了房地产行业的特性和需求,通过整合企业的各个业务…...
学习笔记:黑马程序员JavaWeb开发教程(2024.11.4)
5.8 请求响应-请求-案例 数据保存在emp.xml文件中,解析XML的工具类XMLParserUtils,其中使用了dom4j的接口,因此要在pom.xml文件中引入dom4j的依赖,用于解析XML文件,实体类Emp用于封装服务器解析的数据 前端页面文件…...
开源自托管数据管理工具全面指南
在大数据时代,企业和组织面临着海量的数据挑战。随着应用程序复杂性的提高以及用户需求不断演变,开发团队需要高效地处理大量数据,以便快速做出决策。然而,在众多信息中,如何识别并有效利用那些对决策至关重要的数据呢…...
护工系统|护工陪护软件|护工系统设计
在现代社会,护工系统的开发成为提升医疗服务质量和效率的重要手段。页面设计作为系统开发的关键环节,必须充分考虑到实用性与用户体验。以下是对护工系统开发页面设计功能的详细阐述: 一、用户登录与权限管理 页面设计首先应设置用户登录模块…...
电商领域软件系统实战:基于TiDB的分布式数据库应用
在电商领域,数据的快速增长和复杂性对数据库系统提出了更高要求。TiDB作为一款开源的分布式数据库,以其兼容MySQL协议、水平扩展能力强、高可用性等特性,在电商系统中得到了广泛应用。本文将围绕TiDB在电商领域的应用,详细介绍其搭…...
鸢尾博客项目开源
1.博客介绍 鸢尾博客是一个基于Spring BootVue3 TypeScript ViteJavaFx的客户端和服务器端的博客系统。项目采用前端与后端分离,支持移动端自适应,配有完备的前台和后台管理功能。后端使用Sa-Token进行权限管理,支持动态菜单权限,服务健康…...
Google封号潮来袭!跨境卖家如何解封?
近期,不少小伙伴在苦苦哀嚎:Google账号又又又又被封啦!对于跨境业务在线的小伙伴来说来说,是一个比较严重的问题。但不必过于担心,以下是一些可能的原因和相应的解决方法,耐心看完,也许对你的账号解封有帮助…...
路径规划 | ROS中多个路径规划算法可视化与性能对比分析
目录 0 专栏介绍1 引言2 禁用局部规划器3 路径规划定性对比实验3.1 加载路径规划器和可视化插件3.2 设置起点和终点3.3 选择规划器规划3.4 不同规划器对比3.5 路径保存和加载 4 路径规划定量对比实验4.1 计算规划耗时4.2 计算规划长度4.3 计算拓展节点数4.4 计算路径曲率4.5 计…...
使用 PyCharm 构建 FastAPI 项目:零基础入门 Web API 开发
使用 PyCharm 构建 FastAPI 项目:零基础入门 Web API 开发 本文提供了一份完整的 FastAPI 入门指南,涵盖从环境搭建、依赖安装到创建并运行一个简单的 FastAPI 应用的各个步骤。通过 FastAPI 和 Uvicorn,开发者可以快速构建现代化的 Web API…...
Prim算法与Dijstra算法
注:参考如下文章和视频 不能说毫不相干,简直是一模一样(Prim vs Dijkstra) 普里姆和迪杰斯特拉太像了,他们有什么区别? Prim算法和Dijkstra算法区别 文章目录 总结数组元素的更新两种算法的完整代码 普里姆算法算法步骤算法描…...
水经微图IOS版5.6.1发布,新增图源二维码分享并修订徒步模式功能
随时随地,微图一下! 水经微图(以下称“微图”)IOS版5.6.1发布,本次升级主要新增了图源二维码分享功能,以及修订过往足迹的徒步模式功能。 当前版本 当前版本号为:5.6.1 如果你发现该版本中存…...
复现第三周
1.eval执行 1)打开题目 简单进行代码审计,而题目又为eval函数说明这里eval() 会执行传入的任意代码,可以通过 cmd 作为参数执行任意 PHP 代码,这里相当于用cmd作为参数来执行url头命令 2)在url头输入命令cmdsystem("ls&quo…...
Django---数据库(多表关联)
在Django中操作数据库并实现多表关联,主要是通过定义模型(Models)及其关系,然后利用Django ORM(Object-Relational Mapping)执行数据库操作。 定义模型及其关系 首先,需要在models.py文件中定…...
2024系统架构师---论软件可靠性设计及其应用论文
可靠性 软件可靠性是指软件系统在一定的时间内持续无故障运行的能力。 可靠性通常用平均失效等待时间(MTTF)和平均失效间隔时间(MTBF)来衡量。 影响可靠性的因素 从技术的角度来看,影响软件可靠性的主要因素如下。…...
从HaGRID到自定义:手部关键点数据集标注、转换与可视化实战(Python代码)
从HaGRID到自定义:手部关键点数据集标注、转换与可视化实战(Python代码)在计算机视觉领域,手部关键点检测正逐渐成为人机交互、虚拟现实和手势识别等应用的核心技术。不同于简单的目标检测任务,手部关键点检测需要精确…...
Unity InputField组件保姆级配置指南:从登录框到聊天框,一次搞定所有输入场景
Unity InputField组件实战配置指南:从登录验证到聊天系统的深度优化在游戏开发中,用户输入交互是连接玩家与游戏世界的重要桥梁。Unity的InputField组件作为最常用的输入控件之一,其配置灵活性直接影响用户体验的流畅度。本文将深入探讨如何针…...
OpenClaw强势推出V2026.5.20版本地部署最新教程来啦!3分钟一键安装中文版可视化操作指南
凌晨两点,我刚把 OpenClaw 跑通。看着屏幕上终于亮起来的 WebChat 界面,心里那叫一个舒坦。说实话,之前装了几次都没成功,不是端口冲突就是 API Key 配置不对,折腾了大半天。后来静下心来把文档从头到尾看了一遍&#…...
ThinkPad X1 Carbon摄像头罢工?别急着重装驱动,先试试这个Windows更新‘暂停大法’
ThinkPad X1 Carbon摄像头故障的终极解决方案:Windows更新机制深度解析ThinkPad X1 Carbon作为商务笔记本的标杆产品,其稳定性向来备受赞誉。但最近不少用户反馈遇到了一个令人抓狂的问题——摄像头突然罢工。更令人沮丧的是,按照常规思路重装…...
Qwen模型 LeetCode 2608. 图中的最短环 Java实现
哎呀,2608. 图中的最短环!这题可有意思了~我第一次做时也卡了好一会儿,后来发现用 **BFS 枚举每条边 临时删除** 的思路特别清爽!### 🌟 核心思想: - 对于每一条边 (u, v),我们**暂…...
2026照片去水印免费软件App推荐,详细教程一看就会
你是不是也遇到过这种情况?刷到一张特别喜欢的照片想保存当壁纸,结果右下角一个巨大的水印直接毁了整张图;或者做PPT需要用到某张素材图,翻遍了相册发现都有平台Logo,怎么裁都裁不掉。想找免费的去水印工具,…...
Linux渗透测试实战命令指南:从信息收集到横向移动
1. 这不是命令手册,而是一张渗透测试现场的“作战地图”你有没有过这样的经历:坐在靶机前,刚扫出一个Web服务,脑子里立刻蹦出七八个工具名——nmap、gobuster、sqlmap、hydra……可手一伸向键盘,却卡在了第一个参数上&…...
eClinMed 中国人民解放军总医院第五医学中心介入超声科:基于超声的可解释性机器学习模型用于≤3cm肝细胞癌分类的开发与验证
01文献信息本次分享的文献是由中国人民解放军总医院第五医学中心介入超声科联合厦门大学附属翔安医院、南开大学医学院和福州市第一总医院超声科等55家医院在2025年2月在柳叶刀子刊《eClinicalMedicine》(中科院1区,IF10.0)上的研究“Develop…...
深入解析中兴光猫工厂模式:解锁隐藏网络管理权限的技术探索
深入解析中兴光猫工厂模式:解锁隐藏网络管理权限的技术探索 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 在当今的网络设备管理中,中兴光猫作为广泛部署的终端…...
在Node.js后端服务中集成统一的大模型调用层
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 在Node.js后端服务中集成统一的大模型调用层 在构建现代Web应用时,为不同功能模块引入AI能力已成为提升用户体验和产品…...
