从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)来衡量。 影响可靠性的因素 从技术的角度来看,影响软件可靠性的主要因素如下。…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...
