问题场景:
如果我们使用redis默认的序列化器,会发现redis可视化工具中展示的是乱码,非常不友好
为什么要序列化?
1、如果存储字符串类型的,不需要序列化。但如果存储Bean对象或者集合类型的数据,就必须要序列化
2、对于Bean之类的只需要让它实现Serializable接口就行,反序列化也不需要强转
解决:
配置redisTemplate的序列化器,使用自定义的序列化器,不使用redis默认的,代码如下:
package com.hkl.mpjoin.configure;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.cache.annotation.CachingConfigurerSupport;
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.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import javax.annotation.Resource;
/**
* <p>ClassName: RedisConfigure</p >
* <p>Description: redisTemplate自定义序列化配置,更改其默认序列化器</p >
* <p>Author: hkl</p >
* <p>Date: 2021/10/23</p >
*/
@Configuration
public class RedisConfigure extends CachingConfigurerSupport {
@Resource
private RedisConnectionFactory factory;
@Bean(name = "redisTemplate")
public <K, V> RedisTemplate<K, V> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(
LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.WRAPPER_ARRAY);
//jackson序列化默认存在不认识字段报错,用户可以自己设置将其忽略
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//================================= RedisTemplate 序列化设置 start ==============================
RedisTemplate<K, V> template = new RedisTemplate<K, V>();
template.setConnectionFactory(redisConnectionFactory);
//key、hashKey采用String的序列化方式
//template.setKeySerializer(new GenericToStringSerializer(Object.class));
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
//value、HashValue采用Jackson的序列化方式
template.setValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer(objectMapper));
//初始化函数,使用以上设置的序列化参数
template.afterPropertiesSet();
//设置Redis事务一致支持,可配合@Transactional使用(需要手工关闭连接的谨慎使用)
template.setEnableTransactionSupport(true);
//================================= RedisTemplate 序列化设置 end ================================
return template;
}
@Bean(name = "stringRedisTemplate")
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
//key、value采用String的序列化方式
stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
stringRedisTemplate.setValueSerializer(new StringRedisSerializer());
stringRedisTemplate.setStringSerializer(new StringRedisSerializer());
//初始化函数,使用以上设置的序列化参数
stringRedisTemplate.afterPropertiesSet();
//设置Redis事务一致支持,可配合@Transactional使用(需要手工关闭连接的谨慎使用)
stringRedisTemplate.setEnableTransactionSupport(true);
return stringRedisTemplate;
}
@Bean(name = "redisTemplateTemp")
public RedisTemplate<String, Object> redisTemplateTemp(RedisConnectionFactory redisConnectionFactory) {
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//使用 <String, Object> 泛型,避免类型转换
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
//key、hashKey采用String的序列化方式
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setHashKeySerializer(stringRedisSerializer);
//value、HashValue采用Jackson的序列化方式
redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
//redisTemplate.setEnableDefaultSerializer(true);
//redisTemplate.setDefaultSerializer(new StringRedisSerializer());
//redisTemplate.setStringSerializer(new StringRedisSerializer());
//初始化函数,使用以上设置的序列化参数
redisTemplate.afterPropertiesSet();
//设置Redis事务一致支持,可配合@Transactional使用(需要手工关闭连接的谨慎使用)
redisTemplate.setEnableTransactionSupport(true);
return redisTemplate;
}
}
以上配置好之后,redis可视化端就会正常显示json格式的数据
使用:
注入 redisTemplate 对象即可获取key对应的value
@Resource
RedisTemplate<String, Object> redisTemplate;
注意:
1、最好使用 @Resource 注入,注入的 RedisTemplate 类型、泛型和写入时的 RedisTemplate 类型保持一致,否则可能会出现获取不到value的问题
2、redis 反序列化时所用的dto属性必须全包含序列化时的dto全属性,反序列化所用的dto可以增加属性,但不能删除修改属性,否则会报错找不到对应属性
3、推荐做法:缓存存储时直接存储json字符串,使用时直接把json串反序列化就行了。不推荐redis直接序列化是因为对dto所在的服务、包都有要求,在其他服务中即使同名同属性也无法反序列化,除非使用的还是原来包下的dto才可以,不够灵活
RedisUtil工具类、各个数据类型常用方法及介绍:
package com.hkl.mpjoin.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* <p>Description:Redis工具类</p>
* <p>Description:存储对象实例类型的数据,需要有无参构造方法,否则报错</p>
*
* <p>Author:hkl</p>
* <p>Date:2022/9/15</p>
*/
@Slf4j
@Component
public class RedisUtil {
@Resource(name = "redisTemplate")
private RedisTemplate<String, Object> redisTemplate;
@Resource(name = "stringRedisTemplate")
private StringRedisTemplate stringRedisTemplate;
//################################################## 通用操作 start #################################################
/**
* <p>删除单个key值</p>
*
* @author hkl
* @date 2022/9/15
*/
public boolean delete(String key) {
try {
redisTemplate.delete(key);
return true;
} catch (Exception e) {
log.error("RedisUtil method delete Exception:", e);
}
return false;
}
/**
* <p>批量删除key值</p>
*
* @author hkl
* @date 2022/11/12
*/
public boolean delete(List<String> keys) {
try {
redisTemplate.delete(keys);
return true;
} catch (Exception e) {
log.error("RedisUtil method delete Exception:", e);
}
return false;
}
/**
* <p>把key设置过期时间,默认秒</p>
*
* @author hkl
* @date 2022/11/12
*/
public boolean expire(String key, long time, TimeUnit timeUnit) {
try {
if (ObjectUtil.isNull(timeUnit)) {
timeUnit = TimeUnit.SECONDS;
}
//设置过期时间
redisTemplate.expire(key, time, timeUnit);
return true;
} catch (Exception e) {
log.error("RedisUtil method expire Exception:", e);
}
return false;
}
/**
* <p>设置到指定日期过期</p>
*
* @author hkl
* @date 2022/11/12
*/
public Boolean expireAt(String key, Date date) {
return redisTemplate.expireAt(key, date);
}
/**
* <p>获取匹配的key集合,返回一个Set集合</p>
* <p>例如:获取所有的key【redisTemplate.keys("*")】,获取带前缀的key【redisTemplate.keys(prefix.concat("*"))】</p>
*
* @param pattern 表达式(*、pro_*等),支持模糊匹配
* @author hkl
* @date 2022/11/12
*/
public Set<String> getPatternKey(String pattern) {
return redisTemplate.keys(pattern);
}
/**
* <p>对key重命名</p>
*
* @author hkl
* @date 2022/11/12
*/
public boolean renameKey(String oldKey, String newKey) {
try {
redisTemplate.rename(oldKey, newKey);
return true;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* <p>返回key对应值的类型</p>
*
* @author hkl
* @date 2022/11/12
*/
public DataType getKeyType(String key) {
return redisTemplate.type(key);
}
/**
* <p>如果旧key存在,将旧key改为新key</p>
*
* @author hkl
* @date 2022/11/12
*/
public Boolean renameOldKeyIfAbsent(String oldKey, String newKey) {
try {
if(redisTemplate.hasKey(oldKey)){
return redisTemplate.renameIfAbsent(oldKey, newKey);
}
} catch (Exception e) {
log.error("renameOldKeyIfAbsent出现异常:{}", e.getMessage());
throw new RuntimeException(e);
}
return false;
}
/**
* <p>从keys中随机获取一个key</p>
*
* @author hkl
* @date 2022/11/12
*/
public String getRandomKey() {
return redisTemplate.randomKey();
}
/**
* <p>返回key所对应的剩余过期时间</p>
* <p>-1为没有过期时间</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long getExpire(String key) {
return redisTemplate.getExpire(key);
}
/**
* <p>返回key所对应的剩余过期时间,并指定时间单位</p>
* <p>-1为没有过期时间</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long getExpire(String key, TimeUnit unit) {
return redisTemplate.getExpire(key, unit);
}
/**
* <p>将有过期时间的key持久化保存,改为-1</p>
*
* @author hkl
* @date 2022/11/12
*/
public Boolean persistKey(String key) {
return redisTemplate.persist(key);
}
/**
* <p>将当前数据库的key移动到指定的redis数据库中</p>
* <p>同一个数据库下不可移动,会报错</p>
*
* @author hkl
* @date 2022/11/12
*/
public Boolean moveToDbIndex(String key, int dbIndex) {
return redisTemplate.move(key, dbIndex);
}
/**
* <p>判断 key 是否存在</p>
*
* @author hkl
* @date 2022/9/15
*/
public Boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
log.error("RedisUtil method hasKey Exception:", e);
}
return false;
}
//################################################## 通用操作 end #################################################
//################################################## String类型 start #################################################
/**
* <p>根据key获取value字符串</p>
*
* @author hkl
* @date 2022/9/15
*/
public String getStr(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
/**
* <p>返回key中字符串的截取字符,包含start、end索引</p>
*
* @author hkl
* @date 2022/11/12
*/
public String getStr(String key, long start, long end) {
return stringRedisTemplate.opsForValue().get(key, start, end);
}
/**
* <p>获取多个key对应的值</p>
*
* @return
* @author hkl
* @date 2022/11/12
*/
public List<String> multiGetStr(List<String> keys) {
return stringRedisTemplate.opsForValue().multiGet(keys);
}
/**
* <p>获取key对应的值长度</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long sizeStr(String key) {
return stringRedisTemplate.opsForValue().size(key);
}
/**
* <p>把字符串写入缓存(key有就覆盖没有就添加),key为键、value为值</p>
*
* @author hkl
* @date 2022/9/15
*/
public boolean setStr(String key, String value) {
try {
stringRedisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
log.error("RedisUtil method set Exception:", e);
}
return false;
}
/**
* <p>把字符串写入缓存(key有就覆盖没有就添加),具有时效性(默认为秒)</p>
*
* @author hkl
* @date 2022/9/15
*/
public boolean setStr(String key, String value, long time, TimeUnit timeUnit) {
try {
if (ObjectUtil.isNull(timeUnit)) {
timeUnit = TimeUnit.SECONDS;
}
stringRedisTemplate.opsForValue().set(key, value, time, timeUnit);
return true;
} catch (Exception e) {
log.error("RedisUtil method set Exception:", e);
}
return false;
}
/**
* <p>当key不存在则添加成功返回true,否则不做动作返回false</p>
*
* @author hkl
* @date 2022/11/12
*/
public Boolean setIfAbsentStr(String key, String value) {
return stringRedisTemplate.opsForValue().setIfAbsent(key, value);
}
/**
* <p>写入多个key、value到缓存,字符串类型</p>
* <p>key存在则更新,不存在则添加</p>
*
* @author hkl
* @date 2022/11/12
*/
public void multiSetStr(Map<String, String> map) {
stringRedisTemplate.opsForValue().multiSet(map);
}
/**
* <p>写入多个key、value到缓存,字符串类型</p>
* <p>当全部key都不存在则添加成功返回true,否则不做动作返回false</p>
*
* @author hkl
* @date 2022/11/12
*/
public Boolean multiSetIfAbsentStr(Map<String, String> map) {
return stringRedisTemplate.opsForValue().multiSetIfAbsent(map);
}
/**
* <p>当key存在获取key当前的值,然后把值更新为value,否则添加key、value</p>
*
* @param
* @author hkl
* @date 2022/9/15
*/
public String getAndSetStr(String key, String value) {
try {
return stringRedisTemplate.opsForValue().getAndSet(key, value);
} catch (Exception e) {
log.error("RedisUtil method getAndSet Exception:", e);
}
return "";
}
/**
* <p>当key存在,在key对应的原有值的基础上追加value到末尾,否则添加key、value</p>
* <p>返回追加后的值长度</p>
*
* @author hkl
* @date 2022/11/12
*/
public boolean appendStr(String key, String value) {
try {
Integer append = stringRedisTemplate.opsForValue().append(key, value);
return (ObjectUtil.isNotNull(append) && append > 0);
} catch (Exception e) {
log.error("RedisUtil method append Exception:", e);
}
return false;
}
/**
* <p>以增量方式获取key对应的数值,key不存在则添加,默认值是1,默认增量因子是1</p>
*
* @author hkl
* @date 2022/11/15
*/
public Long increment(String key) {
return stringRedisTemplate.opsForValue().increment(key);
}
/**
* <p>以增量方式获取key对应的数值,increment是增量因子,返回增量之后的结果</p>
* <p>key存在则递增,不存在则添加key、increment</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long increment(String key, long increment) {
return stringRedisTemplate.opsForValue().increment(key, increment);
}
/**
* <p>以增量方式获取key对应的数值,increment是增量因子,返回增量之后的结果</p>
* <p>key存在则递增,不存在则添加key、increment</p>
*
* @author hkl
* @date 2022/11/12
*/
public Double increment(String key, double increment) {
return stringRedisTemplate.opsForValue().increment(key, increment);
}
/**
* <p>以减量方式获取key对应的数值,key不存在则添加,默认值是-1,默认减量因子是1</p>
*
* @author hkl
* @date 2022/11/15
*/
public Long decrement(String key) {
return stringRedisTemplate.opsForValue().decrement(key);
}
/**
* <p>以减量方式获取key对应的数值,key不存在则添加,减量因子是decrement</p>
*
* @author hkl
* @date 2022/11/15
*/
public Long decrement(String key, long decrement) {
return stringRedisTemplate.opsForValue().decrement(key, decrement);
}
/**
* <p>对key所储存的字符串值,获取指定偏移量上的位(bit)</p>
*
* @author hkl
* @date 2022/11/12
*/
public Boolean getBit(String key, Long offset) {
return stringRedisTemplate.opsForValue().getBit(key, offset);
}
/**
* <p>加锁</p>
*
* @author hkl
* @date 2022/9/15
*/
public boolean lock(String key, String value, long time) {
try {
Boolean setIfAbsentRes = stringRedisTemplate.opsForValue().setIfAbsent(key, value);
if (setIfAbsentRes) {
//设置成功,加锁设置过期时间
redisTemplate.expire(key, time, TimeUnit.SECONDS);
return true;
}
} catch (Exception e) {
log.error("RedisUtil method setIfAbsent Exception:", e);
}
return false;
}
/**
* <p>释放锁</p>
*
* @author hkl
* @date 2022/9/15
*/
public boolean unlock(String key, String value) {
try {
String res = stringRedisTemplate.opsForValue().get(key);
if (value.equals(res)) {
redisTemplate.delete(key);
return true;
}
} catch (Exception e) {
log.error("RedisUtil method unlock Exception:", e);
}
return false;
}
//################################################## String类型 end #################################################
//################################################## List类型 start #################################################
/**
* <p>在key列表最左索引处(最前面),添加一个元素</p>
* <p>key不存在则添加key,增量添加元素(List是可重复列表)</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long leftPushList(String key, Object value) {
return redisTemplate.opsForList().leftPush(key, value);
}
/**
* <p>在key列表最左索引处(最前面),添加多个元素</p>
* <p>key不存在则添加key,增量添加元素(List是可重复列表)</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long leftPushAllList(String key, List<Object> values) {
return redisTemplate.opsForList().leftPushAll(key, values);
}
/**
* <p>在key列表中的 pivot 元素前面添加value元素</p>
* <p>pivot元素不存在则不添加</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long leftPushList(String key, Object pivot, Object value) {
return redisTemplate.opsForList().leftPush(key, pivot, value);
}
/**
* <p>key列表存在的时候,在列表最左边添加一个元素,否则不做动作</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long leftPushIfPresentList(String key, Object value) {
return redisTemplate.opsForList().leftPushIfPresent(key, value);
}
/**
* <p>按照先进先出的顺序添加,单个元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long rightPushList(String key, Object value) {
return redisTemplate.opsForList().rightPush(key, value);
}
/**
* <p>按照先进先出的顺序添加,多个元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long rightPushAllList(String key, List<Object> values) {
return redisTemplate.opsForList().rightPushAll(key, values);
}
/**
* <p>按照先进先出的顺序在pivot元素右边添加,单个元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long rightPushList(String key, Object pivot, Object value) {
return redisTemplate.opsForList().rightPush(key, pivot, value);
}
/**
* <p>key列表存在的时候,在列表最左边添加一个元素,否则不做动作</p>
*
* @author hkl
* @date 2022/11/16
*/
public Long rightPushIfPresentList(String key, String value){
return redisTemplate.opsForList().rightPushIfPresent(key, value);
}
/**
* <p>添加指定索引的元素</p>
* <p>覆盖指定索引已有元素。指定索引不可越界,会报错</p>
*
* @author hkl
* @date 2022/11/12
*/
public void setList(String key, long index, Object value) {
redisTemplate.opsForList().set(key, index, value);
}
/**
* <p>根据索引获取key对应列表中的元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public Object indexList(String key, long index) {
return redisTemplate.opsForList().index(key, index);
}
/**
* <p>最好不要范围越界</p>
* <p>获取key列表指定索引范围内的元素(start开始位置、必须大于等于0,end结束位置、可以为负数-1)</p>
* <p>包括startIndex、endIndex元素,startIndex小于0返回空,endIndex为-1返回所有元素</p>
* <p>(0, -1)返回所有元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public List<Object> rangeList(String key, long startIndex, long endIndex) {
return redisTemplate.opsForList().range(key, startIndex, endIndex);
}
/**
* <p>获取并移除key对应列表中最左边第一个元素</p>
* <p>如果列表中没有元素会阻塞列表,直到等待超时或有元素为止</p>
*
* @author hkl
* @date 2022/11/12
*/
public Object leftPopList(String key, long timeout, TimeUnit timeUnit) {
if (ObjectUtil.isNull(timeUnit)) {
timeUnit = TimeUnit.SECONDS;
}
return redisTemplate.opsForList().leftPop(key, timeout, timeUnit);
}
/**
* <p>获取并移除key对应列表中最右边第一个元素</p>
* <p>如果列表中没有元素会阻塞列表,直到等待超时或有元素为止</p>
*
* @author hkl
* @date 2022/11/12
*/
public Object rightPopList(String key, long timeout, TimeUnit timeUnit) {
if (ObjectUtil.isNull(timeUnit)) {
timeUnit = TimeUnit.SECONDS;
}
return redisTemplate.opsForList().rightPop(key, timeout, timeUnit);
}
/**
* <p>从sourceKey列表中取出最后一个元素,把这个元素添加到destinationKey(不存在则新添加)列表中的最左边第一个</p>
* <p>如果列表中没有元素会阻塞列表,直到等待超时或有元素为止</p>
*
* @author hkl
* @date 2022/11/12
*/
public Object rightPopAndLeftPushList(String sourceKey, String destinationKey, long timeout, TimeUnit timeUnit) {
if (ObjectUtil.isNull(timeUnit)) {
timeUnit = TimeUnit.SECONDS;
}
return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey, destinationKey, timeout, timeUnit);
}
/**
* <p>移除key列表中值等于value的元素,这里的index是数量,不是索引</p>
* <p>index=0,删除所有值等于value的元素; index>0,从最左边开始删除第index个值等于value的元素; index<0, 从最右边开始删除第index个值等于value的元素</p>
* <p>返回被删除元素的数量</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long removeList(String key, long index, Object value) {
return redisTemplate.opsForList().remove(key, index, value);
}
/**
* <p>获取key列表的长度</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long sizeList(String key) {
return redisTemplate.opsForList().size(key);
}
/**
* <p>将列表进行裁剪,移除掉start到end之间的元素(包括start不包括end)</p>
*
* @author hkl
* @date 2022/11/12
*/
public void trimList(String key, long start, long end) {
redisTemplate.opsForList().trim(key, start, end);
}
//################################################## List类型 end #################################################
//################################################## Set类型 start #################################################
/**
* <p>向key对应的值set集合中添加元素</p>
* <p>如果添加的元素与集合中的元素重复则不添加,不重复的元素则添加</p>
*
* @author hkl
* @date 2022/11/12
*/
public boolean addSet(String key, Object... values) {
boolean result = false;
try {
Long add = redisTemplate.opsForSet().add(key, values);
result = true;
} catch (Exception e) {
log.error("RedisUtil method add Exception:", e);
}
return result;
}
/**
* <p>向key对应的值set集合中添加元素</p>
* <p>如果添加的元素与集合中的元素重复则不添加,不重复的元素则添加</p>
*
* @author hkl
* @date 2022/11/13
*/
public boolean addSetByList(String key, List<Object> objects) {
try {
if (CollUtil.isEmpty(objects)) {
log.info("objects is null!");
return false;
}
redisTemplate.opsForSet().add(key, ArrayUtil.toArray(objects, Object.class));
return true;
} catch (Exception e) {
log.error("RedisUtil method add Exception:", e);
}
return false;
}
/**
* <p>移除key对应的值set集合中一个或多个元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public boolean removeSet(String key, Object... values) {
boolean result = false;
try {
Long removeRes = redisTemplate.opsForSet().remove(key, values);
if (ObjectUtil.isNotNull(removeRes) && removeRes > 0) {
result = true;
}
} catch (Exception e) {
log.error("RedisUtil method remove Exception:", e);
}
return result;
}
/**
* <p>删除并且返回一个随机的元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public Object popSet(String key) {
return redisTemplate.opsForSet().pop(key);
}
/**
* <p>获取Set集合的大小</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long sizeSet(String key) {
return redisTemplate.opsForSet().size(key);
}
/**
* <p>校验key对应的Set集合是否存在该value</p>
*
* @author hkl
* @date 2022/9/16
*/
public Boolean isMemberSet(String key, Object value) {
return redisTemplate.opsForSet().isMember(key, value);
}
/**
* <p>获取集合的所有元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public Set<Object> membersSet(String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* <p>随机获取集合中的一个元素</p>
*
* @author hkl
* @date 2022/11/12
*/
public Object randomMemberSet(String key) {
return redisTemplate.opsForSet().randomMember(key);
}
// /**
// * <p>获取两个集合的交集(key对应的Set集合和otherKey对应的Set集合,二者集合的交集)</p>
// *
// * @author hkl
// * @date 2022/11/12
// */
// public Set<Object> intersect(String key, String otherKey){
// return redisTemplate.opsForSet().intersect(key, otherKey);
// }
/**
* <p>获取key对应的集合与otherKeyList对应的集合的交集</p>
*
* @author hkl
* @date 2022/11/12
*/
public Set<Object> intersectSet(String key, List<String> otherKeyList) {
return redisTemplate.opsForSet().intersect(key, otherKeyList);
}
// /**
// * <p>key集合与otherKey集合的交集存储到destKey对应的集合中</p>
// *
// * @author hkl
// * @date 2022/11/12
// */
// public Long intersectAndStore(String key, String otherKey, String destKey) {
// return redisTemplate.opsForSet().intersectAndStore(key, otherKey, destKey);
// }
/**
* <p>key对应的集合与otherKeyList对应的集合的交集存储到destKey对应的集合中</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long intersectAndStoreSet(String key, List<String> otherKeyList, String destKey) {
return redisTemplate.opsForSet().intersectAndStore(key, otherKeyList, destKey);
}
/**
* <p>获取key对应的集合与otherKeyList对应的集合的并集</p>
*
* @author hkl
* @date 2022/11/12
*/
public Set<Object> unionSet(String key, List<String> otherKeyList) {
return redisTemplate.opsForSet().union(key, otherKeyList);
}
/**
* <p>key对应集合与otherKeyList对应集合的并集存储到destKey对应的集合中</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long unionAndStoreSet(String key, List<String> otherKeyList, String destKey) {
return redisTemplate.opsForSet().unionAndStore(key, otherKeyList, destKey);
}
/**
* <p>获取两个或多个集合的差集</p>
*
* @author hkl
* @date 2022/11/12
*/
public Set<Object> differenceSet(String key, List<String> otherKeyList) {
return redisTemplate.opsForSet().difference(key, otherKeyList);
}
/**
* <p>两个或多个集合的差集存储到destKey对应的集合中</p>
*
* @author hkl
* @date 2022/11/12
*/
public Long differenceAndStoreSet(String key, List<String> otherKeyList, String destKey) {
return redisTemplate.opsForSet().differenceAndStore(key, otherKeyList, destKey);
}
/**
* <p>遍历set类似于Interator(ScanOptions.NONE为显示所有的)</p>
*
* @author hkl
* @date 2022/11/12
*/
public Cursor<Object> scanSet(String key, ScanOptions options) {
return redisTemplate.opsForSet().scan(key, options);
}
//################################################## Set类型 end #################################################
//################################################## Hash类型 start #################################################
/**
* <p>获取key对应的Map中小key对应的值,没有则返回null</p>
*
* @author hkl
* @date 2022/11/13
*/
public Object getHash(String key, Object hashKey){
return redisTemplate.opsForHash().get(key, hashKey);
}
/**
* <p>获取key对应的完整Map集合</p>
*
* @author hkl
* @date 2022/11/13
* @param
* @return
*/
public Map<Object, Object> entriesHash(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* <p>在key对应的Map中添加键hashKey和值value</p>
* <p>hashKey存在则更新,不存在则添加</p>
*
* @author hkl
* @date 2022/11/13
*/
public void putHash(String key, Object hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
/**
* <p>在key下,以Map集合的形式添加键值</p>
* <p>Map中的小hashKey存在则更新,不存在则添加</p>
*
* @author hkl
* @date 2022/11/13
*/
public void putAllHash(String key, Map<String, Object> maps) {
redisTemplate.opsForHash().putAll(key, maps);
}
/**
* <p>在key对应的Map中,当hashKey不存在则添加键值返回true,存在则不做动作返回false</p>
*
* @author hkl
* @date 2022/11/13
*/
public Boolean putIfAbsentHash(String key, Object hashKey, Object value) {
return redisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
}
/**
* <p>在key对应的Map中,删除一个或者多个小hashKey,小hashKey不存在也不会报错</p>
*
* @author hkl
* @date 2022/11/13
*/
public Long deleteHash(String key, Object... hashKeys) {
return redisTemplate.opsForHash().delete(key, hashKeys);
}
/**
* <p>查看key对应的Map中,是否存在小hashKey</p>
*
* @author hkl
* @date 2022/11/13
*/
public Boolean hasKeyHash(String key, Object hashKey) {
return redisTemplate.opsForHash().hasKey(key, hashKey);
}
/**
* <p>增量方式获取key对应的Map集合中hashKey键的整数值,增量因子是increment</p>
*
* @author hkl
* @date 2022/11/13
*/
public Long incrementHash(String key, Object hashKey, long increment) {
return redisTemplate.opsForHash().increment(key, hashKey, increment);
}
/**
* <p>获取key对应的Map集合中所有键字段</p>
*
* @author hkl
* @date 2022/11/13
*/
public Set<Object> keysHash(String key) {
return redisTemplate.opsForHash().keys(key);
}
/**
* <p>获取key对应的Map集合中键数量</p>
*
* @author hkl
* @date 2022/11/13
*/
public Long sizeHash(String key) {
return redisTemplate.opsForHash().size(key);
}
/**
* <p>获取key对应的Map集合中所有的值</p>
*
* @author hkl
* @date 2022/11/13
*/
public List<Object> valuesHash(String key) {
return redisTemplate.opsForHash().values(key);
}
/**
* <p>在key对应的Map集合中,获取多个小hashKey的值</p>
*
* @author hkl
* @date 2022/11/14
*/
public List<Object> multiGetHash(String key, List<Object> hashKeys) {
return redisTemplate.opsForHash().multiGet(key, hashKeys);
}
/**
* <p>获取key对应的Map集合中小hashKey对应值的长度</p>
* <p>因为多了存储值多了引号,所以长度比预期多2个单位</p>
*
* @author hkl
* @date 2022/11/14
*/
public Long lengthOfValueHash(String key, String hashKey) {
return redisTemplate.opsForHash().lengthOfValue(key, hashKey);
}
/**
* <p>匹配获取键值对,ScanOptions.NONE为获取全部键对</p>
* <p>ScanOptions.scanOptions().match("map1").build() 匹配获取键位map1的键值对,不能模糊匹配</p>
* <p>用法示例:
* Cursor<Map.Entry<Object,Object>> cursor = redisTemplate.opsForHash().scan("hashValue",ScanOptions.scanOptions().match("map1").build());
* while (cursor.hasNext()){
* Map.Entry<Object,Object> entry = cursor.next();
* System.out.println("通过scan(H key, ScanOptions options)方法获取匹配键值对:" + entry.getKey() + "---->" + entry.getValue());
* }
* </p>
*
* @author hkl
* @date 2022/11/13
*/
public Cursor<Map.Entry<Object, Object>> scanHash(String key, ScanOptions options) {
return redisTemplate.opsForHash().scan(key, options);
}
//################################################## Hash类型 end ##################################################
//################################################## 公用验证区域 start ##################################################
public void putAllHashBound(String key, Map<String, Object> map){
redisTemplate.boundHashOps(key).putAll(map);
//redisTemplate.boundHashOps(key).hasKey()
}
//################################################## 公用验证区域 end ####################################################
}