RedisTemplate 工具类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
@SuppressWarnings({"unchecked", "rawtypes", "ConstantConditions"})
@Component
public class RedisCache {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/* ------------------------- 通用操作 ------------------------- */
/**
* 设置缓存键的有效期(默认时间单位:秒)
*
* @param key 缓存键
* @param timeout 有效期时长
* @return 是否设置成功
* @throws IllegalArgumentException 如果 key 为 null
*/
public boolean expire(String key, long timeout) {
return expire(key, timeout, TimeUnit.SECONDS);
}
/**
* 设置缓存键的有效期
*
* @param key 缓存键
* @param timeout 有效期时长
* @param timeUnit 时间单位
* @return 是否设置成功
* @throws IllegalArgumentException 如果 key 或 timeUnit 为 null
*/
public boolean expire(String key, long timeout, TimeUnit timeUnit){validateKey(key);
if (timeUnit == null) throw new IllegalArgumentException("TimeUnit must not be null");
return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, timeUnit));
}
/**
* 获取缓存键的剩余有效期(单位:秒)
*
* @param key 缓存键
* @return 剩余有效期(秒),-2 表示键不存在,-1 表示永久有效
*/
public long getExpire(String key) {validateKey(key);
Long expire = redisTemplate.getExpire(key);
return expire != null ? expire : -2;
}
/**
* 检查缓存键是否存在
*
* @param key 缓存键
* @return 是否存在
* @throws IllegalArgumentException 如果 key 为 null
*/
public boolean hasKey(String key) {validateKey(key);
Boolean hasKey = redisTemplate.hasKey(key);
return Boolean.TRUE.equals(hasKey);
}
/**
* 删除单个缓存键
*
* @param key 缓存键
* @return 是否删除成功
*/
public boolean delete(String key) {validateKey(key);
Boolean deleted = redisTemplate.delete(key);
return Boolean.TRUE.equals(deleted);
}
/**
* 批量删除缓存键
*
* @param keys 缓存键集合
* @return 是否成功删除至少一个键
* @throws IllegalArgumentException 如果 keys 为 null 或空
*/
public boolean delete(Collection<String> keys) {
if (CollectionUtils.isEmpty(keys)) {
throw new IllegalArgumentException("Keys collection must not be empty");}
Long count = redisTemplate.delete(keys);
return count != null && count > 0;
}
/**
* 查找匹配模式的缓存键
*
* @param pattern 键匹配模式(如 "user:*")
* @return 匹配的键集合(可能为空集合)
* @throws IllegalArgumentException 如果 pattern 为 null
*/
public Set<String> keys(String pattern) {
if (pattern == null) throw new IllegalArgumentException("Pattern must not be null");
return redisTemplate.keys(pattern);
}
/* ------------------------- String 操作 ------------------------- */
/**
* 缓存对象(永久有效)
*
* @param key 缓存键
* @param value 缓存值
* @throws IllegalArgumentException 如果 key 或 value 为 null
*/
public <T> void set(String key, T value) {
set(key, value, -1, TimeUnit.SECONDS);}
/**
* 缓存对象并设置有效期
*
* @param key 缓存键
* @param value 缓存值
* @param timeout 有效期时长(<=0 表示永久)
* @param timeUnit 时间单位
* @throws IllegalArgumentException 如果 key 或 value 为 null
*/
public <T> void set(String key, T value, long timeout, TimeUnit timeUnit){validateKey(key);
if (value == null) throw new IllegalArgumentException("Value must not be null");
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
if (timeout > 0){ops.set(key, value, timeout, timeUnit);
} else {ops.set(key, value);
}
}
/**
* 获取缓存对象
*
* @param key 缓存键
* @return 缓存值,不存在时返回 null
* @throws IllegalArgumentException 如果 key 为 null
*/
public <T> T get(String key) {validateKey(key);
ValueOperations<String, Object> ops = redisTemplate.opsForValue();
return (T) ops.get(key);
}
/* ------------------------- Hash 操作 ------------------------- */
/**
* 缓存 Hash 结构数据
*
* @param key 缓存键
* @param hashMap Hash 数据
* @throws IllegalArgumentException 如果 key 或 hashMap 为 null
*/
public <HK, HV> void setHash(String key, Map<HK, HV> hashMap) {validateKey(key);
if (hashMap == null) throw new IllegalArgumentException("HashMap must not be null");
redisTemplate.opsForHash().putAll(key, hashMap);
}
/**
* 获取整个 Hash 结构
*
* @param key 缓存键
* @return 完整的 Hash 数据(可能为空)
*/
public <HK, HV> Map<HK, HV> getHash(String key) {validateKey(key);
return (Map<HK, HV>) redisTemplate.opsForHash().entries(key);
}
/**
* 向 Hash 中添加键值
*
* @param key 缓存键
* @param hKey Hash 键
* @param value Hash 值
*/
public <HK, HV> void putHashValue(String key, HK hKey, HV value) {validateKey(key);
redisTemplate.opsForHash().put(key, hKey, value);
}
/**
* 获取 Hash 中的指定键值
*
* @param key 缓存键
* @param hKey Hash 键
* @return Hash 值,不存在时返回 null
*/
public <HK, HV> HV getHashValue(String key, HK hKey) {validateKey(key);
return (HV) redisTemplate.opsForHash().get(key, hKey);
}
/**
* 删除 Hash 中的指定键
*
* @param key 缓存键
* @param hKeys Hash 键集合
* @return 成功删除的键数量
*/
public <HK> long deleteHashKeys(String key, Collection<HK> hKeys) {validateKey(key);
if (CollectionUtils.isEmpty(hKeys)) return 0;
return redisTemplate.opsForHash().delete(key, hKeys.toArray());
}
/* ------------------------- List 操作 ------------------------- */
/**
* 缓存 List 数据
*
* @param key 缓存键
* @param values 数据列表
* @return 插入后的列表长度
*/
public <T> long setList(String key, List<T> values) {validateKey(key);
if (CollectionUtils.isEmpty(values)) return 0;
Long size = redisTemplate.opsForList().rightPushAll(key, values);
return size != null ? size : 0;
}
/**
* 获取 List 数据
*
* @param key 缓存键
* @param start 起始索引(包含)
* @param end 结束索引(包含,-1 表示末尾)
* @return 指定范围内的数据列表(可能为空)
*/
public <T> List<T> getList(String key, long start, long end){validateKey(key);
return (List<T>) redisTemplate.opsForList().range(key, start, end);
}
/* ------------------------- Set 操作 ------------------------- */
/**
* 缓存 Set 数据
*
* @param key 缓存键
* @param values 数据集
* @return 成功添加的元素数量
*/
public <T> long addToSet(String key, Collection<T> values) {validateKey(key);
if (CollectionUtils.isEmpty(values)) return 0;
Long count = redisTemplate.opsForSet().add(key, values.toArray());
return count != null ? count : 0;
}
/**
* 获取整个 Set 数据
*
* @param key 缓存键
* @return 数据集(可能为空)
*/
public <T> Set<T> getSet(String key) {validateKey(key);
return (Set<T>) redisTemplate.opsForSet().members(key);
}
/* ------------------------- 分布式锁 ------------------------- */
/**
* 尝试获取分布式锁
*
* @param lockKey 锁键
* @param clientId 客户端唯一标识
* @param expireTime 锁的有效期
* @param timeUnit 时间单位
* @return 是否获取成功
*/
public boolean tryLock(String lockKey, String clientId, long expireTime, TimeUnit timeUnit){validateKey(lockKey);
if (clientId == null || timeUnit == null) {
throw new IllegalArgumentException("ClientId and timeUnit must not be null");}
String script = "return redis.call('set', KEYS[1], ARGV[1],'NX','PX', ARGV[2])";
RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
String result = (String) redisTemplate.execute(
redisScript,
Collections.singletonList(lockKey),
clientId,
String.valueOf(timeUnit.toMillis(expireTime))
);
return "OK".equals(result);
}
/**
* 释放分布式锁
*
* @param lockKey 锁键
* @param clientId 客户端唯一标识
* @return 是否释放成功
*/
public boolean releaseLock(String lockKey, String clientId) {validateKey(lockKey);
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
Long result = (Long) redisTemplate.execute(redisScript, Collections.singletonList(lockKey), clientId);
return result != null && result == 1;
}
/* ------------------------- 参数校验 ------------------------- */
private void validateKey(String key) {
if (key == null || key.trim().isEmpty()) {
throw new IllegalArgumentException("Redis key must not be null or empty");}
}
}
License:
CC BY 4.0