参考自:https://www.cnblogs.com/wusiwee/p/10418379.html,并且添加了一些常用的方法。
目录
RedisUtil
注意:
1.里面引入了Hutool下的core.bean.BeanUtil工具类,可以根据自己情况删去或替换成其他工具类。
2.本工具类是在spring data redis 1.8.11版本下测试,新版spring data redis个别api会和下面有所区别,比如ValueOperations.setIfAbsent()新增了过期时间的参数,可以直接保证原子性。新版RedisTemplate.delete()方法新增了是否删除成功的返回值等等。
import cn.hutool.core.bean.BeanUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* redis工具类
*
* @author yz
* @className RedisUtil
* @date 2020/9/2 17:44
*/
@Component
public class RedisUtil<T> {
/**
* slf4j 日志
*/
private final Logger log = LoggerFactory.getLogger(this.getClass());
private final RedisTemplate<String, T> redisTemplate;
/**
* 注入
*
* @param redisTemplate 模板
*/
@Autowired
@SuppressWarnings({"rawtypes", "unchecked"})
public RedisUtil(@Qualifier("redisTemplate") RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 添加 key:string 缓存
*
* @param k key
* @param v value
* @param time time
* @return {@link boolean}
*/
public boolean cacheValue(String k, T v, long time) {
try {
ValueOperations<String, T> ops = redisTemplate.opsForValue();
ops.set(k, v);
if (time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return true;
} catch (Throwable e) {
log.error("缓存存入失败key:[{}] value:[{}]", k, v);
}
return false;
}
/**
* 添加 key:string 缓存
*
* @param key key
* @param value value
* @return {@link boolean}
*/
public boolean cacheValue(String key, T value) {
return cacheValue(key, value, -1);
}
/**
* 当key不存在时添加 key:string 缓存(setNX)
* 当出现异常时会返回{@code null},可以根据实际情况改为false
*
* @param k key
* @param v value
* @param time time
* @return {@link Boolean}
*/
public Boolean cacheValueIfAbsent(String k, T v, long time) {
try {
ValueOperations<String, T> ops = redisTemplate.opsForValue();
Boolean setFlag = ops.setIfAbsent(k, v);
if (setFlag && time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return setFlag;
} catch (Throwable e) {
log.error("setNX执行失败key:[{}] value:[{}]", k, v);
}
return null;
}
/**
* 当key不存在时添加 key:string 缓存(setNX)
* 当出现异常时会返回{@code null},可以根据实际情况改为false
*
* @param key key
* @param value value
* @return {@link Boolean}
*/
public Boolean cacheValueIfAbsent(String key, T value) {
return cacheValueIfAbsent(key, value, -1);
}
/**
* 查询缓存 key 是否存在
*
* @param key key
* @return true/false
*/
public boolean containsKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Throwable e) {
log.error("判断缓存存在失败key:[" + key + "],错误信息 [{}]", e);
}
return false;
}
/**
* 根据 key 获取缓存value
*
* @param key key
* @return value
*/
public T getValue(String key) {
try {
ValueOperations<String, T> ops = redisTemplate.opsForValue();
return ops.get(key);
} catch (Exception e) {
log.error("根据 key 获取缓存失败,当前key:[{}],失败原因:[{}]", key, e);
}
return null;
}
/**
* 扫描符合匹配到的key
*
* @param keyPattern 带通配符的key
* @return value
*/
public Set<String> scan(String keyPattern) {
Set<String> keys = new HashSet<>();
redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
//1000是步进值,过小效率会低一些,尽量与数据级匹配。
ScanOptions so = new ScanOptions.ScanOptionsBuilder().match(keyPattern).count(1000).build();
Cursor<byte[]> cursor = connection.scan(so);
while (cursor.hasNext()) {
keys.add(new String(cursor.next()));
}
return keys;
});
return keys;
}
/**
* 缓存set操作
*
* @param k key
* @param v value
* @param time time
* @return boolean
*/
public boolean cacheSet(String k, T v, long time) {
try {
SetOperations<String, T> opsForSet = redisTemplate.opsForSet();
opsForSet.add(k, v);
if (time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return true;
} catch (Throwable e) {
log.error("缓存 set 失败 当前 key:[{}] 失败原因 [{}]", k, e);
}
return false;
}
/**
* 添加 set 缓存
*
* @param key key
* @param value value
* @return true/false
*/
public boolean cacheSet(String key, T value) {
return cacheSet(key, value, -1);
}
/**
* 添加 缓存 set
*
* @param k key
* @param v value
* @param time 时间/秒
* @return {@link boolean}
*/
public boolean cacheSet(String k, Set<T> v, long time) {
try {
SetOperations<String, T> opsForSet = redisTemplate.opsForSet();
opsForSet.add(k, (T) v.toArray(new String[0]));
if (time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return true;
} catch (Throwable e) {
log.error("缓存 set 失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return false;
}
/**
* 缓存 set
*
* @param k key
* @param v value
* @return {@link boolean}
*/
public boolean cacheSet(String k, Set<T> v) {
return cacheSet(k, v, -1);
}
/**
* 获取缓存set数据
*
* @param k key
* @return set集合
*/
public Set<T> getSet(String k) {
try {
SetOperations<String, T> opsForSet = redisTemplate.opsForSet();
return opsForSet.members(k);
} catch (Throwable e) {
log.error("获取缓存set失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return null;
}
/**
* 缓存hash操作
*
* @param k key
* @param hashKey hashKey
* @param v value
* @param time time
* @return boolean
*/
public boolean cacheHash(String k, String hashKey, T v, long time) {
try {
HashOperations<String, Object, Object> opsForHash = redisTemplate.opsForHash();
opsForHash.put(k, hashKey, v);
if (time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return true;
} catch (Throwable e) {
log.error("缓存 hash 失败 当前 key:[{}] 失败原因 [{}]", k, e);
}
return false;
}
/**
* 根据 key 自增hash 的 value
*
* @param key key
* @param hashKey hashKey
* @param delta 增量
* @return long
*/
public Long incrHash(String key, String hashKey, long delta) {
return redisTemplate.opsForHash().increment(key, hashKey, delta);
}
/**
* 添加 Hash 缓存
*
* @param key key
* @param hashKey hashKey
* @param value value
* @return true/false
*/
public boolean cacheHash(String key, String hashKey, T value) {
return cacheHash(key, hashKey, value, -1);
}
/**
* 添加 缓存 Hash
*
* @param k key
* @param v value Map<String,String>
* @param time 时间/秒
* @return {@link boolean}
*/
public boolean cacheHashAll(String k, Map<String, Object> v, long time) {
try {
HashOperations<String, String, Object> opsForHash = redisTemplate.opsForHash();
opsForHash.putAll(k, v);
if (time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return true;
} catch (Throwable e) {
log.error("缓存 hash 失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return false;
}
/**
* 缓存 hash all
*
* @param k key
* @param v value Map<String,String>
* @return {@link boolean}
*/
public boolean cacheHashAll(String k, Map<String, Object> v) {
return cacheHashAll(k, v, -1);
}
/**
* 缓存 hash all(传入对象形式)
*
* @param k key
* @param v value Object
* @return {@link boolean}
*/
public boolean cacheHashAll4object(String k, Object v) {
return cacheHashAll(k, BeanUtil.beanToMap(v), -1);
}
/**
* 缓存 hash all(传入对象形式)
*
* @param k key
* @param v value Object
* @param time 时间/秒
* @return {@link boolean}
*/
public boolean cacheHashAll4object(String k, Object v, long time) {
return cacheHashAll(k, BeanUtil.beanToMap(v), time);
}
/**
* 缓存 hash all(传入对象形式)
*
* @param k key
* @param v value Object
* @param ignoreNullValue 是否忽略值为空的字段
* @param time 时间/秒
* @return {@link boolean}
*/
public boolean cacheHashAll4object(String k, Object v, boolean ignoreNullValue, long time) {
return cacheHashAll(k, BeanUtil.beanToMap(v,false,true), time);
}
/**
* 获取缓存hash数据
*
* @param k key
* @return String
*/
public T getHash(String k, String hashKey) {
try {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.get(k, hashKey);
} catch (Throwable e) {
log.error("获取缓存 hash 失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return null;
}
/**
* 获取缓存 hash 所有键值对数据
*
* @param k key
* @return Map<String, String>
*/
public Map<String, T> getHashEntry(String k) {
try {
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
return opsForHash.entries(k);
} catch (Throwable e) {
log.error("获取缓存 hash 失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return null;
}
/**
* list 缓存
*
* @param k key
* @param v value
* @param time 时间/秒
* @return true/false
*/
public boolean cacheList(String k, T v, long time) {
try {
ListOperations<String, T> opsForList = redisTemplate.opsForList();
//此处为right push 方法/ 也可以 left push ..
opsForList.rightPush(k, v);
if (time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return true;
} catch (Throwable e) {
log.error("缓存list失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return false;
}
/**
* 缓存 list
*
* @param k key
* @param v value
* @return true/false
*/
public boolean cacheList(String k, T v) {
return cacheList(k, v, -1);
}
/**
* 缓存 list 集合
*
* @param k key
* @param v value
* @param time 时间/秒
* @return {@link boolean}
*/
public boolean cacheList(String k, List<T> v, long time) {
try {
ListOperations<String, T> opsForList = redisTemplate.opsForList();
opsForList.rightPushAll(k, v);
if (time > 0) {
redisTemplate.expire(k, time, TimeUnit.SECONDS);
}
return true;
} catch (Throwable e) {
log.error("缓存list失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return false;
}
/**
* 缓存 list
*
* @param k key
* @param v value
* @return true/false
*/
public boolean cacheList(String k, List<T> v) {
return cacheList(k, v, -1);
}
/**
* 根据 key 获取 list 缓存
*
* @param k key
* @param start 开始
* @param end 结束
* @return 获取缓存区间内 所有value
*/
public List<T> getList(String k, long start, long end) {
try {
ListOperations<String, T> opsForList = redisTemplate.opsForList();
return opsForList.range(k, start, end);
} catch (Throwable e) {
log.error("获取list缓存失败 当前 key:[{}],失败原因 [{}]", k, e);
}
return null;
}
/**
* 根据 key 获取总条数 用于分页
*
* @param key key
* @return 条数
*/
public long getListSize(String key) {
try {
ListOperations<String, T> opsForList = redisTemplate.opsForList();
return opsForList.size(key);
} catch (Throwable e) {
log.error("获取list长度失败key[" + key + "],[" + e + "]");
}
return 0;
}
/**
* 获取总条数 用于分页
*
* @param listOps =redisTemplate.opsForList();
* @param k key
* @return size
*/
public long getListSize(ListOperations<String, String> listOps, String k) {
try {
return listOps.size(k);
} catch (Throwable e) {
log.error("获取list长度失败key[" + k + "],[" + e + "]");
}
return 0;
}
/**
* 根据 key 移除 list 缓存
*
* @param k key
* @return {@link boolean}
*/
public boolean removeOneOfList(String k) {
try {
ListOperations<String, T> opsForList = redisTemplate.opsForList();
opsForList.rightPop(k);
return true;
} catch (Throwable e) {
log.error("移除list缓存失败 key[" + k + "],[" + e + "]");
}
return false;
}
/**
* 根据 key 移除 value 缓存
*
* @param key key
* @return true/false
*/
public boolean removeValue(String key) {
return remove(key);
}
/**
* 根据 key 移除 set 缓存
*
* @param key key
* @return true/false
*/
public boolean removeSet(String key) {
return remove(key);
}
/**
* 根据 key 移除 list 缓存
*
* @param key key
* @return true/false
*/
public boolean removeList(String key) {
return remove(key);
}
/**
* 根据 key 自增value
*
* @param key key
* @return true/false
*/
public Long incr(String key, long delta) {
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 移除缓存
*
* @param key key
* @return boolean
*/
private boolean remove(String key) {
try {
redisTemplate.delete(key);
return true;
} catch (Throwable e) {
log.error("移除缓存失败 key:[{}] 失败原因 [{}]", key, e);
}
return false;
}
}
其他优秀的Redis工具类:https://www.freesion.com/article/4679386590/
springboot整合reids配置
1.加入依赖,会自动下载spring-data-redis包
<!-- 启用redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置文件中配置相关参数(客户端使用的是jedis)
spring:
## Redis 配置
redis:
## Redis数据库索引(默认为0)
database: 0
## Redis服务器地址
host: localhost
## Redis服务器连接端口
port: 6379
## Redis服务器连接密码(默认为空)
password:
jedis:
pool:
## 连接池最大连接数(使用负值表示没有限制)
max-active: 8
## 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1
## 连接池中的最大空闲连接
max-idle: 8
## 连接池中的最小空闲连接
min-idle: 0
## 连接超时时间(毫秒)
timeout: 1200
3.新建配置类,设置一些redis序列化的配置
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* Redis缓存配置类
*
**/
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
/**
* 对hash类型的数据操作
*
* @param redisTemplate redisTemplate
* @return HashOperations<String, String, Object>
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 对redis字符串类型数据操作
*
* @param redisTemplate redisTemplate
* @return ValueOperations<String, Object>
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
/**
* 对链表类型的数据操作
*
* @param redisTemplate redisTemplate
* @return ListOperations<String, Object>
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 对无序集合类型的数据操作
*
* @param redisTemplate redisTemplate
* @return SetOperations<String, Object>
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 对有序集合类型的数据操作
*
* @param redisTemplate redisTemplate
* @return ZSetOperations<String, Object>
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}