从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)来衡量。 影响可靠性的因素 从技术的角度来看,影响软件可靠性的主要因素如下。…...
实战演练:基于快马与豆包开放平台,快速开发智能邮件处理助手
今天想和大家分享一个实战项目:基于豆包开放平台的智能邮件助手开发过程。这个工具特别适合需要频繁处理邮件的职场人士,能自动完成邮件摘要、待办事项提取、回复草拟等重复性工作。 项目背景与需求分析 日常工作中,我们经常要处理大量邮件。…...
Unpaywall终极指南:一键解锁全球学术论文的免费获取方案
Unpaywall终极指南:一键解锁全球学术论文的免费获取方案 【免费下载链接】unpaywall-extension Firefox/Chrome extension that gives you a link to a free PDF when you view scholarly articles 项目地址: https://gitcode.com/gh_mirrors/un/unpaywall-extens…...
Karp的21个NPC问题:从理论到实践的经典探索
1. Karp与NPC问题的历史背景 1971年,Stephen Cook在论文《The Complexity of Theorem Proving Procedures》中首次提出了NP完全性的概念,并证明了布尔可满足性问题(SAT)属于NP完全问题。这一突破性工作为计算复杂性理论奠定了基石…...
别再为YOLOv5标签格式发愁了!手把手教你从COCO128.yaml到txt标签文件的完整配置流程
YOLOv5数据标注全流程实战:从配置文件解析到标签文件生成 刚接触目标检测的新手开发者们,常常在数据准备阶段就陷入迷茫——官方文档过于简略,社区教程又零散不全。本文将彻底解决这个痛点,带你一步步完成YOLOv5数据标注全流程&am…...
3步打造个人数据备份系统:QQ空间数字记忆永久保存指南
3步打造个人数据备份系统:QQ空间数字记忆永久保存指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字化时代,个人数据备份已成为保护数字记忆的关键措施。…...
国之重器 openKylin 入驻 AtomGit:打造全球领先的智能操作系统开源根社区
操作系统是数字基础设施的核心基石,传统 Linux 操作系统用户和开发者经常面临系统软件更新不稳定、存量软件不兼容、开发适配成本高、显示渲染效率低等问题。在 AI 浪潮席卷全球的当下,将 AI 能力与操作系统已成紧密结合,打造智能交互新范式已…...
告别torch.save!用safetensors安全存储PyTorch模型,手把手教你处理metadata(附完整代码)
告别torch.save!用safetensors安全存储PyTorch模型,手把手教你处理metadata(附完整代码) 在深度学习项目的实际开发中,模型参数的保存和加载是每个开发者都必须掌握的基础技能。PyTorch框架默认提供的torch.save和torc…...
MiniCPM-o-4.5-nvidia-FlagOS跨平台部署:Windows系统配置要点
MiniCPM-o-4.5-nvidia-FlagOS跨平台部署:Windows系统配置要点 想在自己的Windows电脑上跑起来最新的MiniCPM-o-4.5-nvidia-FlagOS,结果被一堆环境问题卡住了?别急,这太正常了。很多朋友在Windows上部署这类AI项目时,总…...
YOLOv8特征可视化实战:如何用一行代码查看模型内部特征图(附完整代码)
YOLOv8特征可视化实战:如何用一行代码查看模型内部特征图(附完整代码) 在计算机视觉领域,YOLO系列模型因其卓越的实时检测性能而广受欢迎。但对于开发者而言,仅仅使用模型进行预测往往不够——理解模型内部如何"思…...
如何让Windows高效识别苹果设备?极简驱动安装工具3分钟解决连接难题
如何让Windows高效识别苹果设备?极简驱动安装工具3分钟解决连接难题 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitco…...
