封装Redis模块(最全面的教程!)
1.环境搭建
1.创建模块
2.查看是否交给父模块管理
3.引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sunxiansheng</groupId>
<artifactId>sunrays-common</artifactId>
<version>1.0</version>
</parent>
<version>1.0</version>
<artifactId>common-redis-starter</artifactId>
<dependencies>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<!-- 排除,防止日志冲突 -->
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-logging</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- 集成 redis 所需 commons-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
</project>
4.自动配置
1.目录
2.RedisAutoConfiguration.java
package com.sunxiansheng.redis.config;
import org.springframework.context.annotation.Configuration;
/**
* Description: Redis自动配置类
*
* @Author sun
* @Create 2024/11/15 20:41
* @Version 1.0
*/
@Configuration
public class RedisAutoConfiguration {
}
3.spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.sunxiansheng.redis.config.RedisAutoConfiguration
2.重写RedisTemplate
1.引入Jackson
<!-- 重写RedisTemplate所需要的Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
2.编写RedisConfig.java
package com.sunxiansheng.redis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis配置类,会将 Object 类型序列化为 JSON 格式,然后将其作为字符串存储在 Redis 中。
* 当从 Redis 中读取时,会将 JSON 字符串反序列化回具体的 Object 类型数据,直接强制转换即可,无需手动解析 JSON。
*/
@Configuration
public class RedisConfig {
/**
* 自定义RedisTemplate Bean,配置Key和Value的序列化方式。
* Key采用String序列化,Value采用JSON序列化,支持对象直接转为JSON格式存储在Redis中。
*
* @param redisConnectionFactory Redis连接工厂,用于创建RedisTemplate连接
* @return 配置完成的RedisTemplate实例,用于Redis数据操作
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 设置Key的序列化方式为StringRedisSerializer,以便Key以字符串格式存储,便于人类读取
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(stringSerializer); // 序列化Redis键
redisTemplate.setHashKeySerializer(stringSerializer); // 序列化Hash结构的键
// 设置Value和HashValue的序列化方式为Jackson2JsonRedisSerializer,以便Value以JSON格式存储
Jackson2JsonRedisSerializer<Object> jacksonSerializer = jackson2JsonRedisSerializer();
redisTemplate.setValueSerializer(jacksonSerializer); // 序列化Redis值
redisTemplate.setHashValueSerializer(jacksonSerializer); // 序列化Hash结构的值
// 初始化设置的配置
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 配置Jackson序列化器,以支持复杂Java对象的序列化和反序列化。
* 使用Jackson2JsonRedisSerializer将对象序列化为JSON字符串,从而提高Redis中的可读性和兼容性。
*
* @return 配置好的Jackson2JsonRedisSerializer实例,指定序列化格式为JSON
*/
private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
// 创建Jackson2JsonRedisSerializer,指定泛型为Object,支持序列化任意Java对象
Jackson2JsonRedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 创建ObjectMapper用于配置JSON序列化方式
ObjectMapper objectMapper = new ObjectMapper();
// 设置可见性,允许访问所有字段(包括私有和保护字段),确保所有属性都被序列化和反序列化
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 配置反序列化时忽略未知属性,防止因JSON中多余字段导致反序列化错误
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 序列化时忽略空值属性,节省存储空间
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 启用类型信息,确保反序列化时能够恢复原始对象类型
objectMapper.activateDefaultTyping(
BasicPolymorphicTypeValidator.builder()
.allowIfSubType(Object.class)
.build(),
ObjectMapper.DefaultTyping.NON_FINAL
);
// 将配置好的ObjectMapper设置到Jackson2JsonRedisSerializer中,应用上述配置
jacksonSerializer.setObjectMapper(objectMapper);
return jacksonSerializer;
}
}
3.RedisAutoConfiguration.java 导入配置类
3.Redis工具类
1.RBase.java Redis基础工具类
package com.sunxiansheng.redis.utils;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
/**
* Redis基础工具类,提供一些基础的操作
*
* @Author sun
* @Create 2024/11/14 14:25
* @Version 1.0
*/
public class RBase {
protected RedisTemplate<String, Object> redisTemplate;
public RBase(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 默认的key分隔符
*/
private static final String DEFAULT_KEY_SEPARATOR = ":";
/**
* 构建缓存key(使用默认的key分隔符)
*
* @param parts 多个字符串拼接成缓存key
* @return 拼接后的缓存key
*/
public String buildKeyByDefaultSeparator(String... parts) {
return String.join(DEFAULT_KEY_SEPARATOR, parts);
}
/**
* 构建缓存key(使用自定义的key分隔符)
*
* @param separator 自定义的key分隔符
* @param parts 多个字符串拼接成缓存key
* @return 拼接后的缓存key
*/
public String buildKeyByCustomSeparator(String separator, String... parts) {
return String.join(separator, parts);
}
/**
* 删除单个key
*
* @param key 键
* @return 如果键不存在,返回false;如果删除成功,返回true
*/
public Boolean delete(String key) {
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Key cannot be null or empty");
}
return redisTemplate.delete(key);
}
/**
* 批量删除key
*
* @param keys 键的集合
* @return 成功删除的键的数量,键不存在不计数
*/
public Long deleteBatch(Collection<String> keys) {
if (keys == null || keys.isEmpty()) {
return 0L;
}
return redisTemplate.delete(keys);
}
/**
* 指定缓存失效时间
*
* @param key 键
* @param timeout 失效时间(小于等于0 表示 永久有效)
* @param unit 时间单位
* @return 设置成功返回true,失败返回false
*/
public Boolean expire(String key, long timeout, TimeUnit unit) {
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Key cannot be null or empty");
}
if (timeout <= 0) {
// 或直接返回 true,表示设置为永久有效
return false;
}
return redisTemplate.expire(key, timeout, unit);
}
/**
* 指定缓存失效时间(时间单位:秒)
*
* @param key 键
* @param timeout 失效时间(单位:秒,小于等于0 表示 永久有效)
* @return 设置成功返回true,失败返回false
*/
public Boolean expire(String key, long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 获取缓存失效时间
*
* @param key 键
* @return 缓存失效时间(秒)。键不存在返回-2,键存在但没有设置过期时间返回-1
*/
public Long getExpire(String key) {
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Key cannot be null or empty");
}
return redisTemplate.getExpire(key);
}
/**
* 判断key是否存在
*
* @param key 键
* @return 存在返回true,不存在返回false
*/
public Boolean hasKey(String key) {
if (key == null || key.isEmpty()) {
throw new IllegalArgumentException("Key cannot be null or empty");
}
return redisTemplate.hasKey(key);
}
/**
* 转换缓存中的对象为指定类型
*
* @param value 缓存中的对象
* @param type 要转换的目标类型
* @param <T> 返回的泛型类型
* @return 转换后的对象
* @throws ClassCastException 如果对象不能转换为指定类型
*/
protected <T> T convertValue(Object value, Class<T> type) {
if (value == null) {
return null;
}
// Long类型的特殊处理,因为Redis中的数据会自动反序列化为Integer
if (type == Long.class && value instanceof Integer) {
return type.cast(((Integer) value).longValue());
}
if (type.isInstance(value)) {
return type.cast(value);
} else {
throw new ClassCastException("Redis中的对象运行类型与请求转换的类型不匹配,请优先检查Redis配置类是否保存了对象原始信息!期待类型:"
+ type.getName() + ",实际类型:"
+ value.getClass().getName());
}
}
}
2.RString.java
package com.sunxiansheng.redis.utils;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;
/**
* Description: Redis的String类型操作
*
* @Author sun
* @Create 2024/11/14 14:50
* @Version 1.1
*/
public class RString extends RBase {
/**
* 构造器给父类注入RedisTemplate
*
* @param redisTemplate RedisTemplate实例
*/
public RString(RedisTemplate<String, Object> redisTemplate) {
super(redisTemplate);
}
/**
* 设置缓存值
*
* @param key 键
* @param value 值
*/
public void set(String key, Object value) {
validateKeyAndValue(key, value);
redisTemplate.opsForValue().set(key, value);
}
/**
* 设置缓存值并设置过期时间
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param unit 时间单位
*/
public void setWithExpire(String key, Object value, final long timeout, final TimeUnit unit) {
validateKeyAndValue(key, value);
validateTimeoutAndUnit(timeout, unit);
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
/**
* 设置缓存值并设置过期时间(单位:秒)
*
* @param key 键
* @param value 值
* @param timeout 过期时间
*/
public void setWithExpire(String key, Object value, final long timeout) {
setWithExpire(key, value, timeout, TimeUnit.SECONDS);
}
/**
* 设置缓存值,如果key不存在,则设置成功,并指定过期时间
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @param unit 时间单位
* @return 是否设置成功
*/
public Boolean setIfAbsent(String key, Object value, long timeout, TimeUnit unit) {
validateKeyAndValue(key, value);
validateTimeoutAndUnit(timeout, unit);
return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit);
}
/**
* 设置缓存值,如果key不存在,则设置成功,并指定过期时间(单位:秒)
*
* @param key 键
* @param value 值
* @param timeout 过期时间
* @return 是否设置成功
*/
public Boolean setIfAbsent(String key, Object value, long timeout) {
return setIfAbsent(key, value, timeout, TimeUnit.SECONDS);
}
/**
* 获取缓存值并进行类型转换
*
* @param key 键
* @param type 返回值的类型
* @return 转换后的对象,若类型不匹配则抛出异常
*/
public <T> T get(String key, Class<T> type) {
Object value = redisTemplate.opsForValue().get(key);
return convertValue(value, type);
}
/**
* 获取缓存值并设置新值
*
* @param key 键
* @param value 新值
* @param type 返回值的类型
* @param <T> 返回值的类型
* @return 旧值,类型为 T
*/
public <T> T getAndSet(String key, T value, Class<T> type) {
Object oldValue = redisTemplate.opsForValue().getAndSet(key, value);
return convertValue(oldValue, type);
}
/**
* 根据 delta 值调整缓存中的数值
*
* @param key 键
* @param delta 调整步长,正数表示增加,负数表示减少
* @return 调整后的值
*/
public Long changeByDelta(String key, long delta) {
if (key == null) {
throw new IllegalArgumentException("Key 不能为空!");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 验证键和值的合法性
*/
private void validateKeyAndValue(String key, Object value) {
if (key == null || value == null) {
throw new IllegalArgumentException("Key 和 Value 不能为空!");
}
}
/**
* 验证超时时间和单位的合法性
*/
private void validateTimeoutAndUnit(long timeout, TimeUnit unit) {
if (timeout <= 0 || unit == null) {
throw new IllegalArgumentException("超时时间必须大于 0,时间单位不能为空!");
}
}
}
3.RList.java
package com.sunxiansheng.redis.utils;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Description: Redis的List类型操作
*
* @Author sun
* @Create 2024/11/14 14:50
* @Version 1.0
*/
public class RList extends RBase {
/**
* 构造器给父类注入RedisTemplate
*
* @param redisTemplate RedisTemplate实例
*/
public RList(RedisTemplate<String, Object> redisTemplate) {
super(redisTemplate);
}
/**
* 左侧添加单个值
*
* @param key 键
* @param value 要添加的值
* @return 添加后的List长度
*/
public Long leftPush(String key, Object value) {
return redisTemplate.opsForList().leftPush(key, value);
}
/**
* 左侧批量添加多个值(使用List参数方式)
*
* @param key 键
* @param dataList 要添加的值列表
* @param <V> 值类型
* @return 添加后的List长度,调用方可以忽略返回值
*/
public <V> Long leftPushAll(String key, List<V> dataList) {
return redisTemplate.opsForList().leftPushAll(key, dataList.toArray());
}
/**
* 左侧批量添加多个值(使用Collection参数方式)
*
* @param key 键
* @param dataCollection 要添加的值集合
* @param <V> 值类型
* @return 添加后的List长度
*/
public <V> Long leftPushAll(String key, Collection<V> dataCollection) {
return redisTemplate.opsForList().leftPushAll(key, dataCollection.toArray());
}
/**
* 右侧添加单个值
*
* @param key 键
* @param value 要添加的值
* @return 添加后的List长度
*/
public Long rightPush(String key, Object value) {
return redisTemplate.opsForList().rightPush(key, value);
}
/**
* 右侧批量添加多个值(使用List参数方式)
*
* @param key 键
* @param dataList 要添加的值列表
* @param <V> 值类型
* @return 添加后的List长度
*/
public <V> Long rightPushAll(String key, List<V> dataList) {
return redisTemplate.opsForList().rightPushAll(key, dataList.toArray());
}
/**
* 右侧批量添加多个值(使用Collection参数方式)
*
* @param key 键
* @param dataCollection 要添加的值集合
* @param <V> 值类型
* @return 添加后的List长度
*/
public <V> Long rightPushAll(String key, Collection<V> dataCollection) {
return redisTemplate.opsForList().rightPushAll(key, dataCollection.toArray());
}
/**
* 根据值移除指定数量的匹配元素
*
* @param key 键
* @param count 要移除的元素数量
* @param value 要移除的值
* @return 移除的元素数量
*/
public Long removeByValue(String key, long count, Object value) {
return redisTemplate.opsForList().remove(key, count, value);
}
/**
* 从右侧弹出元素并转换为指定类型
*
* @param key 键
* @param type 期望的返回值类型
* @param <T> 泛型,表示期望的返回类型
* @return 弹出并转换后的元素
*/
public <T> T popRight(String key, Class<T> type) {
Object value = redisTemplate.opsForList().rightPop(key);
return convertValue(value, type);
}
/**
* 从左侧弹出元素并转换为指定类型
*
* @param key 键
* @param type 期望的返回值类型
* @param <T> 泛型,表示期望的返回类型
* @return 弹出并转换后的元素
*/
public <T> T popLeft(String key, Class<T> type) {
Object value = redisTemplate.opsForList().leftPop(key);
return convertValue(value, type);
}
/**
* 根据索引设置List中的值
*
* @param key 键
* @param index 索引位置,从0开始
* @param value 设置的值
*/
public void set(String key, final long index, Object value) {
redisTemplate.opsForList().set(key, index, value);
}
/**
* 获取List中的所有数据,并将每个元素转换为指定类型
*
* @param key 键
* @param type 要转换的值类型
* @param <T> 要转换的值类型
* @return 转换后的List
*/
public <T> List<T> rangeAll(String key, Class<T> type) {
List<Object> range = redisTemplate.opsForList().range(key, 0, -1);
List<T> result = new ArrayList<>();
if (range != null) {
for (Object item : range) {
result.add(convertValue(item, type));
}
}
return result;
}
/**
* 根据索引获取List中的元素并转换为指定类型
*
* @param key 键
* @param index 索引位置,从0开始
* @param type 期望的返回值类型
* @param <T> 泛型,表示期望的返回类型
* @return 转换后的元素
*/
public <T> T getElementByIndex(String key, long index, Class<T> type) {
Object value = redisTemplate.opsForList().index(key, index);
return convertValue(value, type);
}
/**
* 获取List的长度
*
* @param key 键
* @return List的长度
*/
public Long size(String key) {
return redisTemplate.opsForList().size(key);
}
}
4.RSet.java
package com.sunxiansheng.redis.utils;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.HashSet;
import java.util.Set;
/**
* Description: Redis的Set类型操作
*
* @Author sun
* @Create 2024/11/14 14:50
* @Version 1.0
*/
public class RSet extends RBase {
/**
* 构造器给父类注入RedisTemplate
*
* @param redisTemplate RedisTemplate实例
*/
public RSet(RedisTemplate<String, Object> redisTemplate) {
super(redisTemplate);
}
/**
* 添加一个元素
*
* @param key 键
* @param data 值
* @return 添加成功的个数
*/
public Long add(String key, Object data) {
return redisTemplate.opsForSet().add(key, data);
}
/**
* 批量添加元素,并返回添加成功的个数
*
* @param key 键
* @param dataSet 值集合
* @param <T> 添加的元素类型
* @return 添加成功的个数
*/
public <T> Long addBatch(String key, Set<T> dataSet) {
return redisTemplate.opsForSet().add(key, dataSet.toArray());
}
/**
* 移除特定的元素,并返回移除成功的个数
*
* @param key 键
* @param dataSet 要移除的元素集合
* @param <T> 要移除的元素类型
* @return 移除成功的个数
*/
public <T> Long remove(String key, Set<T> dataSet) {
return redisTemplate.opsForSet().remove(key, dataSet.toArray());
}
/**
* 获取集合,并将每个元素转换为指定类型
*
* @param key 键
* @param type 集合中元素的目标类型
* @param <T> 元素的类型
* @return 转换后的集合
*/
public <T> Set<T> members(String key, Class<T> type) {
Set<Object> members = redisTemplate.opsForSet().members(key);
Set<T> result = new HashSet<>();
if (members != null) {
for (Object member : members) {
result.add(convertValue(member, type));
}
}
return result;
}
/**
* 判断集合中是否有该值
*
* @param key 键
* @param data 值
* @return 是否包含该值
*/
public Boolean isMember(String key, Object data) {
return redisTemplate.opsForSet().isMember(key, data);
}
/**
* 获取set的长度
*
* @param key 键
* @return 集合的长度
*/
public Long size(String key) {
return redisTemplate.opsForSet().size(key);
}
}
5.RHash.java
package com.sunxiansheng.redis.utils;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.*;
/**
* Description: Redis的Hash类型操作
*
* @Author sun
* @Create 2024/11/14 14:50
* @Version 1.1
*/
public class RHash extends RBase {
/**
* 构造器给父类注入RedisTemplate
*
* @param redisTemplate RedisTemplate实例
*/
public RHash(RedisTemplate<String, Object> redisTemplate) {
super(redisTemplate);
}
/**
* 设置单个hash值
*
* @param key key
* @param hashKey hashKey
* @param hashValue hashValue
*/
public void put(String key, String hashKey, Object hashValue) {
redisTemplate.opsForHash().put(key, hashKey, hashValue);
}
/**
* 设置多个hash值
*
* @param key key
* @param map map
*/
public void putAll(String key, Map<String, ?> map) {
if (map == null || map.isEmpty()) {
throw new IllegalArgumentException("Map不能为空!");
}
redisTemplate.opsForHash().putAll(key, map);
}
/**
* 删除hash中的一些值
*
* @param key key
* @param hashKeys hashKeys
* @return 删除的个数
*/
public Long delete(String key, List<String> hashKeys) {
if (hashKeys == null || hashKeys.isEmpty()) {
return 0L;
}
return redisTemplate.opsForHash().delete(key, hashKeys.toArray());
}
/**
* 删除hash中的一个值
*
* @param key key
* @param hashKey hashKey
* @return 删除的个数
*/
public Long delete(String key, String hashKey) {
if (hashKey == null) {
return 0L;
}
return redisTemplate.opsForHash().delete(key, hashKey);
}
/**
* 获取单个hash值,并转换为指定类型
*
* @param key key
* @param hashKey hashKey
* @param type 类型
* @param <T> 要转换的类型
* @return hash值
*/
public <T> T getOneMapValue(String key, String hashKey, Class<T> type) {
if (hashKey == null) {
return null;
}
Object object = redisTemplate.opsForHash().get(key, hashKey);
return convertValue(object, type);
}
/**
* 获取多个hash值,并转换为指定类型
*
* @param key Redis键
* @param hashKeys Hash键集合
* @param type 转换的目标类型
* @param <T> 返回的泛型类型
* @return 转换后的Hash对象集合
*/
public <T> List<T> getMultiMapValue(String key, Collection<String> hashKeys, Class<T> type) {
if (hashKeys == null || hashKeys.isEmpty()) {
return Collections.emptyList();
}
Collection<Object> keys = new ArrayList<>(hashKeys);
List<Object> objects = redisTemplate.opsForHash().multiGet(key, keys);
List<T> result = new ArrayList<>();
for (Object obj : objects) {
result.add(convertValue(obj, type));
}
return result;
}
/**
* 获取所有键值对,并将其转换为指定类型
*
* @param key 键
* @param type 返回值的类型
* @param <T> 值类型
* @return 转换后的Map,键为String类型,值为T类型
*/
public <T> Map<String, T> getAll(String key, Class<T> type) {
Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
if (entries.isEmpty()) {
return Collections.emptyMap();
}
Map<String, T> result = new HashMap<>();
for (Map.Entry<Object, Object> entry : entries.entrySet()) {
if (entry.getKey() instanceof String) {
String strKey = (String) entry.getKey();
T value = convertValue(entry.getValue(), type);
result.put(strKey, value);
} else {
throw new ClassCastException("Redis中Hash的键不是String类型:实际类型为 " + entry.getKey().getClass().getName());
}
}
return result;
}
/**
* 判断hash中是否存在某个键
*
* @param key key
* @param hashKey hashKey
* @return 是否存在
*/
public Boolean hasHashKey(String key, String hashKey) {
if (hashKey == null) {
return false;
}
return redisTemplate.opsForHash().hasKey(key, hashKey);
}
}
6.RSortedSet.java
package com.sunxiansheng.redis.utils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
/**
* Description: Redis的ZSet类型操作
*
* @Author sun
* @Create 2024/11/14 14:50
* @Version 1.0
*/
public class RSortedSet extends RBase {
/**
* 构造器给父类注入RedisTemplate
*
* @param redisTemplate RedisTemplate实例
*/
public RSortedSet(RedisTemplate<String, Object> redisTemplate) {
super(redisTemplate);
}
/**
* 添加一个元素,并设置分数
*
* @param key 键
* @param data 元素
* @param score 分数
* @return 是否添加成功,成功返回true
*/
public Boolean add(String key, Object data, double score) {
return redisTemplate.opsForZSet().add(key, data, score);
}
/**
* 自定义的数据分数类型,用于批量添加元素
*
* @param <T> 元素的类型
*/
public static class DataScore<T> {
/**
* 数据
*/
private T data;
/**
* 分数
*/
private Double score;
public DataScore() {
}
public DataScore(T data, Double score) {
this.data = data;
this.score = score;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
}
/**
* 批量添加元素,并设置分数
*
* @param key 键
* @param dataScores 自定义数据结构集合,包含元素及分数
* @param <T> 元素的类型
* @return 添加成功的元素数量
*/
public <T> Long addBatch(String key, Set<DataScore<T>> dataScores) {
// 将 Set<DataScore<T>> 转换为 Set<ZSetOperations.TypedTuple<Object>>
Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
for (DataScore<T> dataScore : dataScores) {
tuples.add(new ZSetOperations.TypedTuple<Object>() {
@Override
public Object getValue() {
return dataScore.getData(); // 调用 getData 方法
}
@Override
public Double getScore() {
return dataScore.getScore();
}
/**
* 比较器,从大到小排序
*/
@Override
public int compareTo(ZSetOperations.TypedTuple<Object> o) {
return Double.compare(o.getScore(), this.getScore());
}
});
}
// 添加到 Redis 的 ZSet
return redisTemplate.opsForZSet().add(key, tuples);
}
/**
* 移除特定的元素
*
* @param key 键
* @param dataSet 要移除的元素集合
* @param <T> 元素类型
* @return 移除成功的元素数量
*/
public <T> Long remove(String key, Set<T> dataSet) {
return redisTemplate.opsForZSet().remove(key, dataSet.toArray());
}
/**
* 删除指定分数范围的元素
*
* @param key 键
* @param min 最小分数
* @param max 最大分数
* @return 删除成功的元素数量
*/
public Long removeRangeByScore(String key, double min, double max) {
return redisTemplate.opsForZSet().removeRangeByScore(key, min, max);
}
/**
* 根据delta值调整指定元素的分数
*
* @param key 键
* @param data 元素
* @param delta 增加或减少的分数值
* @return 调整后的分数
*/
public Double changeByDelta(String key, Object data, double delta) {
return redisTemplate.opsForZSet().incrementScore(key, data, delta);
}
/**
* 获取全部ZSet元素(分数从大到小),并将值转换为指定类型
*
* @param key Redis键
* @param type 元素的目标类型
* @param <T> 元素类型
* @return 转换后的ZSet集合,包含分值和对应的值
*/
public <T> Set<ZSetOperations.TypedTuple<T>> reverseRangeWithScores(String key, Class<T> type) {
// 获取 Redis 中的 ZSet 数据
Set<ZSetOperations.TypedTuple<Object>> typedTuples = redisTemplate.opsForZSet().reverseRangeWithScores(key, 0, -1);
// 使用 TreeSet 并提供自定义比较器,从大到小排序
Set<ZSetOperations.TypedTuple<T>> result = new TreeSet<>((a, b) -> Double.compare(b.getScore(), a.getScore()));
// 遍历并进行类型转换
if (typedTuples != null) {
for (ZSetOperations.TypedTuple<Object> tuple : typedTuples) {
T value = convertValue(tuple.getValue(), type);
Double score = tuple.getScore();
result.add(new ZSetOperations.TypedTuple<T>() {
@Override
public T getValue() {
return value;
}
@Override
public Double getScore() {
return score;
}
/**
* 比较器,从大到小排序
*/
@Override
public int compareTo(ZSetOperations.TypedTuple<T> o) {
return Double.compare(o.getScore(), this.getScore());
}
});
}
}
return result;
}
/**
* 获取指定元素的分数
*
* @param key 键
* @param data 元素
* @return 元素的分数
*/
public Double score(String key, Object data) {
return redisTemplate.opsForZSet().score(key, data);
}
/**
* 获取指定元素的排名(从大到小)
*
* @param key 键
* @param data 元素
* @return 排名(从0开始)
*/
public Long reverseRank(String key, Object data) {
return redisTemplate.boundZSetOps(key).reverseRank(data);
}
/**
* 获取ZSet中的元素总数
*
* @param key 键
* @return 元素个数
*/
public Long zCard(String key) {
return redisTemplate.opsForZSet().zCard(key);
}
/**
* 获取指定分数范围内的元素数量
*
* @param key 键
* @param min 最小分数
* @param max 最大分数
* @return 元素数量
*/
public Long count(String key, double min, double max) {
return redisTemplate.opsForZSet().count(key, min, max);
}
}
4.测试
1.创建测试模块
2.引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.sunxiansheng</groupId>
<artifactId>sunrays-demo</artifactId>
<version>1.0</version>
</parent>
<artifactId>common-redis-starter-demo</artifactId>
<dependencies>
<!-- 引入自定义的 common-redis-starter -->
<dependency>
<groupId>com.sunxiansheng</groupId>
<artifactId>common-redis-starter</artifactId>
<version>1.0</version>
</dependency>
<!-- 引入自定义的 common-log4j2-starter -->
<dependency>
<groupId>com.sunxiansheng</groupId>
<artifactId>common-log4j2-starter</artifactId>
<version>1.0</version>
</dependency>
<!-- 引入自定义的 common-web-starter -->
<dependency>
<groupId>com.sunxiansheng</groupId>
<artifactId>common-web-starter</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
3.启动类
package com.sunxiansheng.redis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Description: Redis启动类
*
* @Author sun
* @Create 2024/11/15 20:56
* @Version 1.0
*/
@SpringBootApplication
public class RedisApplication {
public static void main(String[] args) {
SpringApplication.run(RedisApplication.class, args);
}
}
4.编写application.yml
spring:
redis:
host: # Redis服务器地址
port: # Redis服务器端口
password: # Redis服务器密码
database: 0 # 默认数据库为0号
timeout: 1800000 # 连接超时时间是1800秒
lettuce:
pool:
max-active: 20 # 最大活跃连接数,使用负值表示没有限制
max-wait: -1 # 最大等待时间,单位为毫秒,使用负值表示没有限制
max-idle: 10 # 最大空闲连接数
min-idle: 0 # 最小空闲连接数
5.测试
1.RStringController.java
package com.sunxiansheng.redis.controller;
import com.sunxiansheng.redis.utils.RString;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
/**
* Description: 测试 RString 工具类的 Controller
*
* @Author sun
* @Create 2024/11/14 15:20
* @Version 1.0
*/
@RestController
@RequestMapping("/rstring")
public class RStringController {
@Resource
private RString rString;
/**
* 设置缓存值
*/
@PostMapping("/set")
public String set(@RequestParam String key, @RequestParam Long value) {
rString.set(key, value);
return "Value set successfully!";
}
/**
* 设置缓存值并设置过期时间
*/
@PostMapping("/setWithExpire")
public String setWithExpire(@RequestParam String key,
@RequestParam Long value,
@RequestParam long timeout) {
rString.setWithExpire(key, value, timeout);
return "Value set with expiration successfully!";
}
/**
* 设置缓存值并设置过期时间(自定义时间单位)
*/
@PostMapping("/setWithExpireUnit")
public String setWithExpireUnit(@RequestParam String key,
@RequestParam Long value,
@RequestParam long timeout) {
rString.setWithExpire(key, value, timeout, TimeUnit.DAYS);
return "Value set with custom expiration successfully!";
}
/**
* 设置缓存值,如果key不存在,则设置成功
*/
@PostMapping("/setIfAbsent")
public String setIfAbsent(@RequestParam String key,
@RequestParam Long value,
@RequestParam long timeout) {
boolean result = rString.setIfAbsent(key, value, timeout);
return result ? "Value set successfully!" : "Key already exists!";
}
/**
* 获取缓存值
*/
@GetMapping("/get")
public Long get(@RequestParam String key) {
return rString.get(key, Long.class);
}
/**
* 获取缓存值并设置新值
*/
@PostMapping("/getAndSet")
public Long getAndSet(@RequestParam String key, @RequestParam Long value) {
return rString.getAndSet(key, value, Long.class);
}
/**
* 根据 delta 值调整缓存中的数值
*/
@PostMapping("/changeByDelta")
public Long changeByDelta(@RequestParam String key, @RequestParam long delta) {
return rString.changeByDelta(key, delta);
}
}
2.RListController.java
package com.sunxiansheng.redis.controller;
import com.sunxiansheng.redis.utils.RList;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 测试 RList 工具类的 Controller
*
* @Author sun
* @Create 2024/11/14 16:00
* @Version 1.0
*/
@RestController
@RequestMapping("/rlist")
public class RListController {
@Autowired
private RList rList;
/**
* 左侧添加单个值
*/
@PostMapping("/leftPush")
public String leftPush(@RequestParam String key, @RequestBody User user) {
rList.leftPush(key, user);
return "User added to the left of the list.";
}
/**
* 左侧批量添加多个值
*/
@PostMapping("/leftPushAll")
public String leftPushAll(@RequestParam String key, @RequestBody List<User> users) {
rList.leftPushAll(key, users);
return "Users added to the left of the list.";
}
/**
* 右侧添加单个值
*/
@PostMapping("/rightPush")
public String rightPush(@RequestParam String key, @RequestBody User user) {
rList.rightPush(key, user);
return "User added to the right of the list.";
}
/**
* 右侧批量添加多个值
*/
@PostMapping("/rightPushAll")
public String rightPushAll(@RequestParam String key, @RequestBody List<User> users) {
rList.rightPushAll(key, users);
return "Users added to the right of the list.";
}
/**
* 根据索引设置List中的值
*/
@PutMapping("/set")
public String set(@RequestParam String key, @RequestParam int index, @RequestBody User user) {
rList.set(key, index, user);
return "User updated at index " + index;
}
/**
* 获取List中的所有数据
*/
@GetMapping("/rangeAll")
public List<User> rangeAll(@RequestParam String key) {
return rList.rangeAll(key, User.class);
}
/**
* 根据索引获取List中的元素
*/
@GetMapping("/getElementByIndex")
public User getElementByIndex(@RequestParam String key, @RequestParam int index) {
return rList.getElementByIndex(key, index, User.class);
}
/**
* 获取List的长度
*/
@GetMapping("/size")
public Long size(@RequestParam String key) {
return rList.size(key);
}
/**
* 从右侧弹出元素
*/
@DeleteMapping("/popRight")
public User popRight(@RequestParam String key) {
return rList.popRight(key, User.class);
}
/**
* 从左侧弹出元素
*/
@DeleteMapping("/popLeft")
public User popLeft(@RequestParam String key) {
return rList.popLeft(key, User.class);
}
/**
* 根据值移除指定数量的匹配元素
*/
@DeleteMapping("/removeByValue")
public String removeByValue(@RequestParam String key, @RequestParam int count, @RequestBody User user) {
Long removedCount = rList.removeByValue(key, count, user);
return removedCount + " matching users removed.";
}
}
/**
* 简单的自定义类型 User
*
* @Author sun
* @Create 2024/11/14 15:50
* @Version 1.0
*/
@NoArgsConstructor
@Data
@AllArgsConstructor
class User implements java.io.Serializable {
private String id;
private String name;
}
3.RSetController.java
package com.sunxiansheng.redis.controller;
import com.sunxiansheng.redis.utils.RSet;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.Serializable;
import java.util.Set;
/**
* Description: RSet的测试Controller
*
* @Author sun
* @Create 2024/11/15
* @Version 1.0
*/
@RestController
@RequestMapping("/rset")
public class RSetController {
@Autowired
private RSet rSet;
/**
* 静态内部类表示简单的自定义对象
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class Element implements Serializable {
private Long id;
private String name;
}
/**
* 添加一个元素
*/
@PostMapping("/add")
public Long add(@RequestParam String key, @RequestBody Element element) {
return rSet.add(key, element);
}
/**
* 批量添加元素
*/
@PostMapping("/addBatch")
public Long addBatch(@RequestParam String key, @RequestBody Set<Element> elements) {
return rSet.addBatch(key, elements);
}
/**
* 移除元素
*/
@PostMapping("/remove")
public Long remove(@RequestParam String key, @RequestBody Set<Element> elements) {
return rSet.remove(key, elements);
}
/**
* 获取集合
*/
@GetMapping("/members")
public Set<Element> members(@RequestParam String key) {
return rSet.members(key, Element.class);
}
/**
* 判断是否包含某元素
*/
@GetMapping("/isMember")
public Boolean isMember(@RequestParam String key, @RequestBody Element element) {
return rSet.isMember(key, element);
}
/**
* 获取集合大小
*/
@GetMapping("/size")
public Long size(@RequestParam String key) {
return rSet.size(key);
}
}
4.RHashController.java
package com.sunxiansheng.redis.controller;
import com.sunxiansheng.redis.utils.RHash;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/rhash")
public class RHashController {
private final RHash rHash;
public RHashController(RHash rHash) {
this.rHash = rHash;
}
@NoArgsConstructor
@AllArgsConstructor
@Data
public static class User {
private Long id;
private String name;
private Integer age;
}
/**
* 设置单个hash值
*/
@PostMapping("/put")
public void put(@RequestParam String key, @RequestParam String hashKey, @RequestBody User user) {
rHash.put(key, hashKey, user);
}
/**
* 设置多个hash值
*/
@PostMapping("/putAll")
public void putAll(@RequestParam String key, @RequestBody Map<String, User> userMap) {
rHash.putAll(key, userMap);
}
/**
* 删除hash中的多个值
*/
@DeleteMapping("/deleteMultiple")
public Long deleteMultiple(@RequestParam String key, @RequestBody List<String> hashKeys) {
return rHash.delete(key, hashKeys);
}
/**
* 删除hash中的单个值
*/
@DeleteMapping("/deleteSingle")
public Long deleteSingle(@RequestParam String key, @RequestParam String hashKey) {
return rHash.delete(key, hashKey);
}
/**
* 获取单个hash值并转换为指定类型
*/
@GetMapping("/getOne")
public User getOneMapValue(@RequestParam String key, @RequestParam String hashKey) {
return rHash.getOneMapValue(key, hashKey, User.class);
}
/**
* 获取多个hash值并转换为指定类型
*/
@GetMapping("/getMulti")
public List<User> getMultiMapValue(@RequestParam String key, @RequestBody List<String> hashKeys) {
return rHash.getMultiMapValue(key, hashKeys, User.class);
}
/**
* 获取所有键值对并转换为指定类型
*/
@GetMapping("/getAll")
public Map<String, User> getAll(@RequestParam String key) {
return rHash.getAll(key, User.class);
}
/**
* 判断hash中是否存在某个键
*/
@GetMapping("/hasHashKey")
public Boolean hasHashKey(@RequestParam String key, @RequestParam String hashKey) {
return rHash.hasHashKey(key, hashKey);
}
}
5.RSortedSetController.java
package com.sunxiansheng.redis.controller;
import com.sunxiansheng.redis.utils.RSortedSet;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.*;
import java.util.Set;
/**
* Description: 测试 RSortedSet 工具类
*
* @Author sun
* @Create 2024/11/16
* @Version 1.0
*/
@RestController
@RequestMapping("/rsortedset")
public class RSortedSetController {
@Autowired
private RSortedSet rSortedSet;
// 自定义类型
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class CustomValue {
private Long id;
private String name;
}
@PostMapping("/add")
public Boolean add(@RequestParam String key, @RequestBody CustomValue value, @RequestParam double score) {
return rSortedSet.add(key, value, score);
}
@PostMapping("/addBatch")
public Long addBatch(@RequestParam String key, @RequestBody Set<RSortedSet.DataScore<CustomValue>> dataScores) {
return rSortedSet.addBatch(key, dataScores);
}
@PostMapping("/remove")
public Long remove(@RequestParam String key, @RequestBody Set<CustomValue> values) {
return rSortedSet.remove(key, values);
}
@PostMapping("/removeRangeByScore")
public Long removeRangeByScore(@RequestParam String key, @RequestParam double min, @RequestParam double max) {
return rSortedSet.removeRangeByScore(key, min, max);
}
@PostMapping("/changeByDelta")
public Double changeByDelta(@RequestParam String key, @RequestBody CustomValue value, @RequestParam double delta) {
return rSortedSet.changeByDelta(key, value, delta);
}
@GetMapping("/reverseRangeWithScores")
public Set<ZSetOperations.TypedTuple<CustomValue>> reverseRangeWithScores(@RequestParam String key) {
return rSortedSet.reverseRangeWithScores(key, CustomValue.class);
}
@GetMapping("/score")
public Double score(@RequestParam String key, @RequestBody CustomValue value) {
return rSortedSet.score(key, value);
}
@GetMapping("/reverseRank")
public Long reverseRank(@RequestParam String key, @RequestBody CustomValue value) {
return rSortedSet.reverseRank(key, value);
}
@GetMapping("/zCard")
public Long zCard(@RequestParam String key) {
return rSortedSet.zCard(key);
}
@GetMapping("/count")
public Long count(@RequestParam String key, @RequestParam double min, @RequestParam double max) {
return rSortedSet.count(key, min, max);
}
}
原文地址:https://blog.csdn.net/m0_64637029/article/details/145191503
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!