从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)来衡量。 影响可靠性的因素 从技术的角度来看,影响软件可靠性的主要因素如下。…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制
目录 节点的功能承载层(GATT/Adv)局限性: 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能,如 Configuration …...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...