基於 RedisTemplate 自定義 Redis 操作類
阿新 • • 發佈:2019-12-31
歡迎糾錯!!!
該操作類基於自定義的 RedisTemplate,關於自定義 RedisTemplate,請參考Spring Boot 2.0 整合 redis
BaseRedisOperator
該類的設計思路是,與 Redis 命令語法及格式保持一致,以達到使用該類與直接使用 Redis 命令相似的體驗。
由於 Redis 命令眾多,並沒有實現全部的命令,而是實現了常用的大部分命令。
封裝好後沒有進行測試,僅供參考
package com.wqlm.boot.user.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component
public class BaseRedisOperator {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
enum Position {
BEFORE,AFTER
}
/**************************************************** key 相關操作 *************************************************/
/**
* 實現命令 : KEYS pattern
* 查詢所有符合 pattern 模式的 key
* ? 匹配單個字元
* * 匹配0到多個字元
* [a-c] 匹配a和c
* [ac] 匹配a到c
* [^a] 匹配除了a以外的字元
*
* @param pattern redis pattern 表示式
* @return
*/
public Set<String> keys(String pattern) {
return redisTemplate.keys(pattern);
}
/**
* 實現命令 : DEL key1 [key2 ...]
* 刪除一個或多個key
*
* @param keys
* @return
*/
public Long del(String... keys) {
Set<String> keySet = Stream.of(keys).collect(Collectors.toSet());
return redisTemplate.delete(keySet);
}
/**
* 實現命令 : UNLINK key1 [key2 ...]
* 刪除一個或多個key
*
* @param keys
* @return
*/
public Long unlink(String... keys) {
Set<String> keySet = Stream.of(keys).collect(Collectors.toSet());
return redisTemplate.unlink(keySet);
}
/**
* 實現命令 : EXISTS key1 [key2 ...]
* 檢視 key 是否存在,返回存在 key 的個數
*
* @param keys
* @return
*/
public Long exists(String... keys) {
Set<String> keySet = Stream.of(keys).collect(Collectors.toSet());
return redisTemplate.countExistingKeys(keySet);
}
/**
* 實現命令 : TYPE key
* 檢視 key 的 value 的型別
*
* @param key
* @return
*/
public String type(String key) {
DataType dataType = redisTemplate.type(key);
if (dataType == null) {
return "";
}
return dataType.code();
}
/**
* 實現命令 : PERSIST key
* 取消 key 的超時時間,持久化 key
*
* @param key
* @return
*/
public boolean persist(String key) {
Boolean result = redisTemplate.persist(key);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令 : TTL key
* 返回給定 key 的剩餘生存時間,key不存在返回 null
* 單位: 秒
*
* @param key
* @return
*/
public Long ttl(String key) {
return redisTemplate.getExpire(key);
}
/**
* 實現命令 : PTTL key
* 返回給定 key 的剩餘生存時間,key不存在返回 null
* 單位: 毫秒
*
* @param key
* @return
*/
public Long pTtl(String key) {
return redisTemplate.getExpire(key,TimeUnit.MILLISECONDS);
}
/**
* 實現命令 : EXPIRE key 秒
* 設定key 的生存時間
* 單位 : 秒
*
* @param key
* @return
*/
public boolean expire(String key,int ttl) {
Boolean result = redisTemplate.expire(key,ttl,TimeUnit.SECONDS);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令 : PEXPIRE key 毫秒
* 設定key 的生存時間
* 單位 : 毫秒
*
* @param key
* @return
*/
public boolean pExpire(String key,Long ttl) {
Boolean result = redisTemplate.expire(key,TimeUnit.MILLISECONDS);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令 : EXPIREAT key Unix時間戳(自1970年1月1日以來的秒數)
* 設定key 的過期時間
*
* @param key
* @param date
* @return
*/
public boolean expireAt(String key,Date date) {
Boolean result = redisTemplate.expireAt(key,date);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令 : RENAME key newkey
* 重新命名key,如果newKey已經存在,則newKey的原值被覆蓋
*
* @param oldKey
* @param newKey
*/
public void rename(String oldKey,String newKey) {
redisTemplate.rename(oldKey,newKey);
}
/**
* 實現命令 : RENAMENX key newkey
* 安全重新命名key,newKey不存在時才重新命名
*
* @param oldKey
* @param newKey
* @return
*/
public boolean renameNx(String oldKey,String newKey) {
Boolean result = redisTemplate.renameIfAbsent(oldKey,newKey);
if (null == result) {
return false;
}
return result;
}
/**************************************************** key 相關操作 *************************************************/
/************************************************* String 相關操作 *************************************************/
/**
* 實現命令 : SET key value
* 新增一個持久化的 String 型別的鍵值對
*
* @param key
* @param value
*/
public void set(String key,Object value) {
redisTemplate.opsForValue().set(key,value);
}
/**
* 實現命令 : SET key value EX 秒、 setex key value 秒
* 新增一個 String 型別的鍵值對,並設定生存時間
*
* @param key
* @param value
* @param ttl key 的生存時間,單位:秒
*/
public void set(String key,Object value,int ttl) {
redisTemplate.opsForValue().set(key,value,TimeUnit.SECONDS);
}
/**
* 實現命令 : SET key value PX 毫秒 、 psetex key value 毫秒
* 新增一個 String 型別的鍵值對,並設定生存時間
*
* @param key
* @param value
* @param ttl key 的生存時間,單位:毫秒
*/
public void set(String key,long ttl) {
redisTemplate.opsForValue().set(key,TimeUnit.MILLISECONDS);
}
/**
* 實現命令 : SET key value [EX 秒|PX 毫秒] [NX|XX]
* 新增一個 String 型別的鍵值對,
* ttl、timeUnit 不為 null 時設定生存時間
* keyIfExist 不為 null 時,設定 NX 或 XX 模式
*
* @param key
* @param value
* @param ttl 生存時間
* @param timeUnit 生存時間的單位
* @param keyIfExist true 表示 xx,key 存在時才新增. false 表示 nx,key 不存在時才新增
*/
public boolean set(String key,Long ttl,TimeUnit timeUnit,Boolean keyIfExist) {
Boolean result = false;
if ((ttl == null || timeUnit == null) && (keyIfExist == null)) {
// SET key value
redisTemplate.opsForValue().set(key,value);
result = true;
}
if (ttl != null && timeUnit != null && keyIfExist == null) {
// SET key value [EX 秒|PX 毫秒]
redisTemplate.opsForValue().set(key,timeUnit);
result = true;
}
if ((ttl == null || timeUnit == null) && (keyIfExist != null) && keyIfExist) {
// SET key value XX
result = redisTemplate.opsForValue().setIfPresent(key,value);
}
if (ttl != null && timeUnit != null && keyIfExist != null && keyIfExist) {
// SET key value [EX 秒|PX 毫秒] XX
result = redisTemplate.opsForValue().setIfPresent(key,timeUnit);
}
if ((ttl == null || timeUnit == null) && (keyIfExist != null) && (!keyIfExist)) {
// SET key value NX
result = redisTemplate.opsForValue().setIfAbsent(key,value);
}
if (ttl != null && timeUnit != null && keyIfExist != null && (!keyIfExist)) {
// SET key value [EX 秒|PX 毫秒] NX
result = redisTemplate.opsForValue().setIfAbsent(key,timeUnit);
}
if (result == null) {
return false;
}
return result;
}
/**
* 實現命令 : MSET key1 value1 [key2 value2...]
* 安全批量新增鍵值對,只要有一個 key 已存在,所有的鍵值對都不會插入
*
* @param keyValueMap
*/
public void mSet(Map<String,Object> keyValueMap) {
redisTemplate.opsForValue().multiSetIfAbsent(keyValueMap);
}
/**
* 實現命令 : MSETNX key1 value1 [key2 value2...]
* 批量新增鍵值對
*
* @param keyValueMap
*/
public void mSetNx(Map<String,Object> keyValueMap) {
redisTemplate.opsForValue().multiSet(keyValueMap);
}
/**
* 實現命令 : SETRANGE key 下標 str
* 覆蓋 原始 value 的一部分,從指定的下標開始覆蓋, 覆蓋的長度為指定的字串的長度。
*
* @param key
* @param str 字串
* @param offset 開始覆蓋的位置,包括開始位置,下標從0開始
*/
public void setRange(String key,Object str,int offset) {
redisTemplate.opsForValue().set(key,str,offset);
}
/**
* 實現命令 : APPEND key value
* 在原始 value 末尾追加字串
*
* @param key
* @param str 要追加的字串
*/
public void append(String key,String str) {
redisTemplate.opsForValue().append(key,str);
}
/**
* 實現命令 : GETSET key value
* 設定 key 的 value 並返回舊 value
*
* @param key
* @param value
*/
public Object getSet(String key,Object value) {
return redisTemplate.opsForValue().getAndSet(key,value);
}
/**
* 實現命令 : GET key
* 獲取一個key的value
*
* @param key
* @return value
*/
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
/**
* 實現命令 : MGET key1 [key2...]
* 獲取多個key的value
*
* @param keys
* @return value
*/
public List<Object> mGet(String... keys) {
Set<String> keySet = Stream.of(keys).collect(Collectors.toSet());
return redisTemplate.opsForValue().multiGet(keySet);
}
/**
* 實現命令 : GETRANGE key 開始下標 結束下標
* 獲取指定key的value的子串,下標從0開始,包括開始下標,也包括結束下標。
*
* @param key
* @param start 開始下標
* @param end 結束下標
* @return
*/
public String getRange(String key,int start,int end) {
return redisTemplate.opsForValue().get(key,start,end);
}
/**
* 實現命令 : STRLEN key
* 獲取 key 對應 value 的字串長度
*
* @param key
* @return
*/
public Long strLen(String key) {
return redisTemplate.opsForValue().size(key);
}
/**
* 實現命令 : INCR key
* 給 value 加 1,value 必須是整數
*
* @param key
* @return
*/
public Long inCr(String key) {
return redisTemplate.opsForValue().increment(key);
}
/**
* 實現命令 : INCRBY key 整數
* 給 value 加 上一個整數,value 必須是整數
*
* @param key
* @return
*/
public Long inCrBy(String key,Long number) {
return redisTemplate.opsForValue().increment(key,number);
}
/**
* 實現命令 : INCRBYFLOAT key 數
* 給 value 加上一個小數,value 必須是數
*
* @param key
* @return
*/
public Double inCrByFloat(String key,double number) {
return redisTemplate.opsForValue().increment(key,number);
}
/**
* 實現命令 : DECR key
* 給 value 減去 1,value 必須是整數
*
* @param key
* @return
*/
public Long deCr(String key) {
return redisTemplate.opsForValue().decrement(key);
}
/**
* 實現命令 : DECRBY key 整數
* 給 value 減去一個整數,value 必須是整數
*
* @param key
* @return
*/
public Long deCcrBy(String key,Long number) {
return redisTemplate.opsForValue().decrement(key,number);
}
/************************************************* String 相關操作 *************************************************/
/************************************************* Hash 相關操作 ***************************************************/
/**
* 實現命令 : HSET key field value
* 新增 hash 型別的鍵值對,如果欄位已經存在,則將其覆蓋。
*
* @param key
* @param field
* @param value
*/
public void hSet(String key,String field,Object value) {
redisTemplate.opsForHash().put(key,field,value);
}
/**
* 實現命令 : HSET key field1 value1 [field2 value2 ...]
* 新增 hash 型別的鍵值對,如果欄位已經存在,則將其覆蓋。
*
* @param key
* @param map
*/
public void hSet(String key,Map<String,Object> map) {
redisTemplate.opsForHash().putAll(key,map);
}
/**
* 實現命令 : HSETNX key field value
* 新增 hash 型別的鍵值對,如果欄位不存在,才新增
*
* @param key
* @param field
* @param value
*/
public boolean hSetNx(String key,Object value) {
Boolean result = redisTemplate.opsForHash().putIfAbsent(key,value);
if (result == null) {
return false;
}
return result;
}
/**
* 實現命令 : HGET key field
* 返回 field 對應的值
*
* @param key
* @param field
* @return
*/
public Object hGet(String key,String field) {
return redisTemplate.opsForHash().get(key,field);
}
/**
* 實現命令 : HMGET key field1 [field2 ...]
* 返回 多個 field 對應的值
*
* @param key
* @param fields
* @return
*/
public List<Object> hGet(String key,String... fields) {
Set<Object> fieldSet = Stream.of(fields).collect(Collectors.toSet());
return redisTemplate.opsForHash().multiGet(key,fieldSet);
}
/**
* 實現命令 : HGETALL key
* 返回所以的鍵值對
*
* @param key
* @return
*/
public Map<Object,Object> hGetAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 實現命令 : HKEYS key
* 獲取所有的 field
*
* @param key
* @return
*/
public Set<Object> hKeys(String key) {
return redisTemplate.opsForHash().keys(key);
}
/**
* 實現命令 : HVALS key
* 獲取所有的 value
*
* @param key
* @return
*/
public List<Object> hValue(String key) {
return redisTemplate.opsForHash().values(key);
}
/**
* 實現命令 : HDEL key field [field ...]
* 刪除雜湊表 key 中的一個或多個指定域,不存在的域將被忽略。
*
* @param key
* @param fields
*/
public Long hDel(String key,Object... fields) {
return redisTemplate.opsForHash().delete(key,fields);
}
/**
* 實現命令 : HEXISTS key field
* 刪除雜湊表 key 中的一個或多個指定域,不存在的域將被忽略。
*
* @param key
* @param field
*/
public boolean hExists(String key,String field) {
Boolean result = redisTemplate.opsForHash().hasKey(key,field);
if (result == null) {
return false;
}
return result;
}
/**
* 實現命令 : HLEN key
* 獲取 hash 中欄位:值對的數量
*
* @param key
*/
public Long hLen(String key) {
return redisTemplate.opsForHash().size(key);
}
/**
* 實現命令 : HSTRLEN key field
* 獲取欄位對應值的長度
*
* @param key
* @param field
*/
public Long hStrLen(String key,String field) {
return redisTemplate.opsForHash().lengthOfValue(key,field);
}
/**
* 實現命令 : HINCRBY key field 整數
* 給欄位的值加上一個整數
*
* @param key
* @param field
* @return 運算後的值
*/
public Long hInCrBy(String key,long number) {
return redisTemplate.opsForHash().increment(key,number);
}
/**
* 實現命令 : HINCRBYFLOAT key field 浮點數
* 給欄位的值加上一個浮點數
*
* @param key
* @param field
* @return 運算後的值
*/
public Double hInCrByFloat(String key,Double number) {
return redisTemplate.opsForHash().increment(key,number);
}
/************************************************* Hash 相關操作 ***************************************************/
/************************************************* List 相關操作 ***************************************************/
/**
* 實現命令 : LPUSH key 元素1 [元素2 ...]
* 在最左端推入元素
*
* @param key
* @param values
* @return 執行 LPUSH 命令後,列表的長度。
*/
public Long lPush(String key,Object... values) {
return redisTemplate.opsForList().leftPushAll(key,values);
}
/**
* 實現命令 : RPUSH key 元素1 [元素2 ...]
* 在最右端推入元素
*
* @param key
* @param values
* @return 執行 RPUSH 命令後,列表的長度。
*/
public Long rPush(String key,Object... values) {
return redisTemplate.opsForList().rightPushAll(key,values);
}
/**
* 實現命令 : LPOP key
* 彈出最左端的元素
*
* @param key
* @return 彈出的元素
*/
public Object lPop(String key) {
return redisTemplate.opsForList().leftPop(key);
}
/**
* 實現命令 : RPOP key
* 彈出最右端的元素
*
* @param key
* @return 彈出的元素
*/
public Object rPop(String key) {
return redisTemplate.opsForList().rightPop(key);
}
/**
* 實現命令 : BLPOP key
* (阻塞式)彈出最左端的元素,如果 key 中沒有元素,將一直等待直到有元素或超時為止
*
* @param key
* @param timeout 等待的時間,單位秒
* @return 彈出的元素
*/
public Object bLPop(String key,int timeout) {
return redisTemplate.opsForList().leftPop(key,timeout,TimeUnit.SECONDS);
}
/**
* 實現命令 : BRPOP key
* (阻塞式)彈出最右端的元素,將一直等待直到有元素或超時為止
*
* @param key
* @return 彈出的元素
*/
public Object bRPop(String key,int timeout) {
return redisTemplate.opsForList().rightPop(key,TimeUnit.SECONDS);
}
/**
* 實現命令 : LINDEX key index
* 返回指定下標處的元素,下標從0開始
*
* @param key
* @param index
* @return 指定下標處的元素
*/
public Object lIndex(String key,int index) {
return redisTemplate.opsForList().index(key,index);
}
/**
* 實現命令 : LINSERT key BEFORE|AFTER 目標元素 value
* 在目標元素前或後插入元素
*
* @param key
* @param position
* @param pivot
* @param value
* @return
*/
public Long lInsert(String key,Position position,Object pivot,Object value) {
switch (position) {
case AFTER:
return redisTemplate.opsForList().rightPush(key,pivot,value);
case BEFORE:
return redisTemplate.opsForList().rightPush(key,value);
default:
return null;
}
}
/**
* 實現命令 : LRANGE key 開始下標 結束下標
* 獲取指定範圍的元素,下標從0開始,包括開始下標,也包括結束下標(待驗證)
*
* @param key
* @param start
* @param end
* @return
*/
public List<Object> lRange(String key,int end) {
return redisTemplate.opsForList().range(key,end);
}
/**
* 實現命令 : LLEN key
* 獲取 list 的長度
*
* @param key
* @return
*/
public Long lLen(String key) {
return redisTemplate.opsForList().size(key);
}
/**
* 實現命令 : LREM key count 元素
* 刪除 count 個指定元素,*
* @param key
* @param count count > 0: 從頭往尾移除指定元素。count < 0: 從尾往頭移除指定元素。count = 0: 移除列表所有的指定元素。(未驗證)
* @param value
* @return
*/
public Long lLen(String key,int count,Object value) {
return redisTemplate.opsForList().remove(key,count,value);
}
/**
* 實現命令 : LSET key index 新值
* 更新指定下標的值,下標從 0 開始,支援負下標,-1表示最右端的元素(未驗證)
*
* @param key
* @param index
* @param value
* @return
*/
public void lSet(String key,int index,Object value) {
redisTemplate.opsForList().set(key,index,value);
}
/**
* 實現命令 : LTRIM key 開始下標 結束下標
* 裁剪 list。[01234] 的 `LTRIM key 1 -2` 的結果為 [123]
*
* @param key
* @param start
* @param end
* @return
*/
public void lTrim(String key,int end) {
redisTemplate.opsForList().trim(key,end);
}
/**
* 實現命令 : RPOPLPUSH 源list 目標list
* 將 源list 的最右端元素彈出,推入到 目標list 的最左端,
*
* @param sourceKey 源list
* @param targetKey 目標list
* @return 彈出的元素
*/
public Object rPopLPush(String sourceKey,String targetKey) {
return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,targetKey);
}
/**
* 實現命令 : BRPOPLPUSH 源list 目標list timeout
* (阻塞式)將 源list 的最右端元素彈出,推入到 目標list 的最左端,如果 源list 沒有元素,將一直等待直到有元素或超時為止
*
* @param sourceKey 源list
* @param targetKey 目標list
* @param timeout 超時時間,單位秒, 0表示無限阻塞
* @return 彈出的元素
*/
public Object bRPopLPush(String sourceKey,String targetKey,int timeout) {
return redisTemplate.opsForList().rightPopAndLeftPush(sourceKey,targetKey,TimeUnit.SECONDS);
}
/************************************************* List 相關操作 ***************************************************/
/************************************************** SET 相關操作 ***************************************************/
/**
* 實現命令 : SADD key member1 [member2 ...]
* 新增成員
*
* @param key
* @param values
* @return 新增成功的個數
*/
public Long sAdd(String key,Object... values) {
return redisTemplate.opsForSet().add(key,values);
}
/**
* 實現命令 : SREM key member1 [member2 ...]
* 刪除指定的成員
*
* @param key
* @param values
* @return 刪除成功的個數
*/
public Long sRem(String key,Object... values) {
return redisTemplate.opsForSet().remove(key,values);
}
/**
* 實現命令 : SCARD key
* 獲取set中的成員數量
*
* @param key
* @return
*/
public Long sCard(String key) {
return redisTemplate.opsForSet().size(key);
}
/**
* 實現命令 : SISMEMBER key member
* 檢視成員是否存在
*
* @param key
* @param values
* @return
*/
public boolean sIsMember(String key,Object... values) {
Boolean result = redisTemplate.opsForSet().isMember(key,values);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令 : SMEMBERS key
* 獲取所有的成員
*
* @param key
* @return
*/
public Set<Object> sMembers(String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 實現命令 : SMOVE 源key 目標key member
* 移動成員到另一個集合
*
* @param sourceKey 源key
* @param targetKey 目標key
* @param value
* @return
*/
public boolean sMove(String sourceKey,Object value) {
Boolean result = redisTemplate.opsForSet().move(sourceKey,targetKey);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令 : SDIFF key [otherKey ...]
* 求 key 的差集
*
* @param key
* @param otherKeys
* @return
*/
public Set<Object> sDiff(String key,String... otherKeys) {
List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
return redisTemplate.opsForSet().difference(key,otherKeyList);
}
/**
* 實現命令 : SDIFFSTORE 目標key key [otherKey ...]
* 儲存 key 的差集
*
* @param targetKey 目標key
* @param key
* @param otherKeys
* @return
*/
public Long sDiffStore(String targetKey,String key,String... otherKeys) {
List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
return redisTemplate.opsForSet().differenceAndStore(key,otherKeyList,targetKey);
}
/**
* 實現命令 : SINTER key [otherKey ...]
* 求 key 的交集
*
* @param key
* @param otherKeys
* @return
*/
public Set<Object> sInter(String key,String... otherKeys) {
List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
return redisTemplate.opsForSet().intersect(key,otherKeyList);
}
/**
* 實現命令 : SINTERSTORE 目標key key [otherKey ...]
* 儲存 key 的交集
*
* @param targetKey 目標key
* @param key
* @param otherKeys
* @return
*/
public Long sInterStore(String targetKey,String... otherKeys) {
List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
return redisTemplate.opsForSet().intersectAndStore(key,targetKey);
}
/**
* 實現命令 : SUNION key [otherKey ...]
* 求 key 的並集
*
* @param key
* @param otherKeys
* @return
*/
public Set<Object> sUnion(String key,String... otherKeys) {
List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
return redisTemplate.opsForSet().union(key,otherKeyList);
}
/**
* 實現命令 : SUNIONSTORE 目標key key [otherKey ...]
* 儲存 key 的並集
*
* @param targetKey 目標key
* @param key
* @param otherKeys
* @return
*/
public Long sUnionStore(String targetKey,String... otherKeys) {
List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
return redisTemplate.opsForSet().unionAndStore(key,targetKey);
}
/**
* 實現命令 : SPOP key [count]
* 隨機刪除(彈出)指定個數的成員
*
* @param key
* @return
*/
public Object sPop(String key) {
return redisTemplate.opsForSet().pop(key);
}
/**
* 實現命令 : SPOP key [count]
* 隨機刪除(彈出)指定個數的成員
*
* @param key
* @param count 個數
* @return
*/
public List<Object> sPop(String key,int count) {
return redisTemplate.opsForSet().pop(key,count);
}
/**
* 實現命令 : SRANDMEMBER key [count]
* 隨機返回指定個數的成員
*
* @param key
* @return
*/
public Object sRandMember(String key) {
return redisTemplate.opsForSet().randomMember(key);
}
/**
* 實現命令 : SRANDMEMBER key [count]
* 隨機返回指定個數的成員
* 如果 count 為正數,隨機返回 count 個不同成員
* 如果 count 為負數,隨機選擇 1 個成員,返回 count 個
*
* @param key
* @param count 個數
* @return
*/
public List<Object> sRandMember(String key,int count) {
return redisTemplate.opsForSet().randomMembers(key,count);
}
/************************************************** SET 相關操作 ***************************************************/
/*********************************************** Sorted SET 相關操作 ***********************************************/
/**
* 實現命令 : ZADD key score member
* 新增一個 成員/分數 對
*
* @param key
* @param value 成員
* @param score 分數
* @return
*/
public boolean zAdd(String key,double score,Object value) {
Boolean result = redisTemplate.opsForZSet().add(key,score);
if (result == null) {
return false;
}
return result;
}
/**
* 實現命令 : ZREM key member [member ...]
* 刪除成員
*
* @param key
* @param values
* @return
*/
public Long zRem(String key,Object... values) {
return redisTemplate.opsForZSet().remove(key,values);
}
/**
* 實現命令 : ZREMRANGEBYRANK key start stop
* 刪除 start下標 和 end下標間的所有成員
* 下標從0開始,支援負下標,-1表示最右端成員,包括開始下標也包括結束下標 (未驗證)
*
* @param key
* @param start 開始下標
* @param end 結束下標
* @return
*/
public Long zRemRangeByRank(String key,int end) {
return redisTemplate.opsForZSet().removeRange(key,end);
}
/**
* 實現命令 : ZREMRANGEBYSCORE key start stop
* 刪除分數段內的所有成員
* 包括min也包括max (未驗證)
*
* @param key
* @param min 小分數
* @param max 大分數
* @return
*/
public Long zRemRangeByScore(String key,double min,double max) {
return redisTemplate.opsForZSet().removeRangeByScore(key,min,max);
}
/**
* 實現命令 : ZSCORE key member
* 獲取成員的分數
*
* @param key
* @param value
* @return
*/
public Double zScore(String key,Object value) {
return redisTemplate.opsForZSet().score(key,value);
}
/**
* 實現命令 : ZINCRBY key 帶符號的雙精度浮點數 member
* 增減成員的分數
*
* @param key
* @param value
* @param delta 帶符號的雙精度浮點數
* @return
*/
public Double zInCrBy(String key,double delta) {
return redisTemplate.opsForZSet().incrementScore(key,delta);
}
/**
* 實現命令 : ZCARD key
* 獲取集合中成員的個數
*
* @param key
* @return
*/
public Long zCard(String key) {
return redisTemplate.opsForZSet().size(key);
}
/**
* 實現命令 : ZCOUNT key min max
* 獲取某個分數範圍內的成員個數,包括min也包括max (未驗證)
*
* @param key
* @param min 小分數
* @param max 大分數
* @return
*/
public Long zCount(String key,double max) {
return redisTemplate.opsForZSet().count(key,max);
}
/**
* 實現命令 : ZRANK key member
* 按分數從小到大獲取成員在有序集合中的排名
*
* @param key
* @param value
* @return
*/
public Long zRank(String key,Object value) {
return redisTemplate.opsForZSet().rank(key,value);
}
/**
* 實現命令 : ZREVRANK key member
* 按分數從大到小獲取成員在有序集合中的排名
*
* @param key
* @param value
* @return
*/
public Long zRevRank(String key,Object value) {
return redisTemplate.opsForZSet().reverseRank(key,value);
}
/**
* 實現命令 : ZRANGE key start end
* 獲取 start下標到 end下標之間到成員,並按分數從小到大返回
* 下標從0開始,支援負下標,-1表示最後一個成員,包括開始下標,也包括結束下標(未驗證)
*
* @param key
* @param start 開始下標
* @param end 結束下標
* @return
*/
public Set<Object> zRange(String key,int end) {
return redisTemplate.opsForZSet().range(key,end);
}
/**
* 實現命令 : ZREVRANGE key start end
* 獲取 start下標到 end下標之間到成員,並按分數從小到大返回
* 下標從0開始,支援負下標,-1表示最後一個成員,包括開始下標,也包括結束下標(未驗證)
*
* @param key
* @param start 開始下標
* @param end 結束下標
* @return
*/
public Set<Object> zRevRange(String key,int end) {
return redisTemplate.opsForZSet().reverseRange(key,end);
}
/**
* 實現命令 : ZRANGEBYSCORE key min max
* 獲取分數範圍內的成員並按從小到大返回
* (未驗證)
*
* @param key
* @param min 小分數
* @param max 大分數
* @return
*/
public Set<Object> zRangeByScore(String key,double max) {
return redisTemplate.opsForZSet().rangeByScore(key,max);
}
/**
* 實現命令 : ZRANGEBYSCORE key min max LIMIT offset count
* 分頁獲取分數範圍內的成員並按從小到大返回
* 包括min也包括max(未驗證)
*
* @param key
* @param min 小分數
* @param max 大分數
* @param offset 開始下標,下標從0開始
* @param count 取多少條
* @return
*/
public Set<Object> zRangeByScore(String key,double max,int offset,int count) {
return redisTemplate.opsForZSet().rangeByScore(key,max,offset,count);
}
/**
* 實現命令 : ZREVRANGEBYSCORE key min max
* 獲取分數範圍內的成員並按從大到小返回
* (未驗證)
*
* @param key
* @param min 小分數
* @param max 大分數
* @return
*/
public Set<Object> zRevRangeByScore(String key,double max) {
return redisTemplate.opsForZSet().reverseRangeByScore(key,max);
}
/**
* 實現命令 : ZREVRANGEBYSCORE key min max LIMIT offset count
* 分頁獲取分數範圍內的成員並按從大到小返回
* 包括min也包括max(未驗證)
*
* @param key
* @param min 小分數
* @param max 大分數
* @param offset 開始下標,下標從0開始
* @param count 取多少條
* @return
*/
public Set<Object> zRevRangeByScore(String key,int count) {
return redisTemplate.opsForZSet().reverseRangeByScore(key,count);
}
/*********************************************** Sorted SET 相關操作 ***********************************************/
}
複製程式碼
RedisOperator
RedisOperator 類在 BaseRedisOperator 的基礎上補充了一下無法按照 Redis 命令 設計的類。
使用該類並不會給你帶來類似直接使用Redis 命令的體驗
封裝好後沒有進行測試,僅供參考
package com.wqlm.boot.user.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class RedisOperator extends BaseRedisOperator {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
/**************************************************** key 相關操作 *************************************************/
/**
* 實現命令:DEL key1 [key2 ...]
* 刪除任意多個 key
*
* @param keys
* @return
*/
public Long del(Collection<String> keys) {
Set<String> keySet = new HashSet<>(keys);
return redisTemplate.delete(keySet);
}
/**
* 實現命令:UNLINK key1 [key2 ...]
* 刪除任意多個 key
*
* @param keys
* @return
*/
public Long unlink(Collection<String> keys) {
Set<String> keySet = new HashSet<>(keys);
return redisTemplate.unlink(keySet);
}
/**
* 實現命令:EXISTS key1 [key2 ...]
* key去重後,檢視 key 是否存在,返回存在 key 的個數
*
* @param keys
* @return
*/
public Long exists(Collection<String> keys) {
Set<String> keySet = new HashSet<>(keys);
return redisTemplate.countExistingKeys(keySet);
}
/**
* 實現命令:EXPIREAT key Unix時間戳(自1970年1月1日以來的秒數)
* 設定key 的過期時間
*
* @param key
* @param ttl 存活時間 單位秒
* @return
*/
public boolean expireAt(String key,int ttl) {
Date date = new Date(System.currentTimeMillis() + ttl * 1000);
Boolean result = redisTemplate.expireAt(key,date);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令:PEXPIREAT key 自1970年1月1日以來的毫秒數
* 設定key 的過期時間
*
* @param key
* @param ttl 存活時間 單位毫秒
* @return
*/
public boolean pExpireAt(String key,long ttl) {
Date date = new Date(System.currentTimeMillis() + ttl);
Boolean result = redisTemplate.expireAt(key,date);
if (null == result) {
return false;
}
return result;
}
/**
* 實現命令 : PEXPIREAT key 自1970年1月1日以來的毫秒數
* 設定key 的過期時間
*
* @param key
* @param date
* @return
*/
public boolean pExpireAt(String key,date);
if (null == result) {
return false;
}
return result;
}
/**************************************************** key 相關操作 *************************************************/
/************************************************* String 相關操作 *************************************************/
/**
* 實現命令 : MGET key1 [key2...]
* key去重後,獲取多個key的value
*
* @param keys
* @return value
*/
public List<Object> mGet(Collection<String> keys) {
Set<String> keySet = new HashSet<>(keys);
return redisTemplate.opsForValue().multiGet(keySet);
}
/************************************************* String 相關操作 *************************************************/
/************************************************* Hash 相關操作 ***************************************************/
/**
* 實現命令 : HMGET key field1 [field2 ...]
* 返回 多個 field 對應的值
*
* @param key
* @param fields
* @return
*/
public List<Object> hGet(String key,Collection<Object> fields) {
return redisTemplate.opsForHash().multiGet(key,fields);
}
/**
* 實現命令 : HDEL key field [field ...]
* 刪除雜湊表 key 中的一個或多個指定域,不存在的域將被忽略。
*
* @param key
* @param fields
*/
public Long hDel(String key,Collection<Object> fields) {
Object[] objects = fields.toArray();
return redisTemplate.opsForHash().delete(key,objects);
}
/************************************************* Hash 相關操作 ***************************************************/
/************************************************* List 相關操作 ***************************************************/
/**
* 實現命令 : LPUSH key 元素1 [元素2 ...]
* 在最左端推入元素
*
* @param key
* @param values
* @return 執行 LPUSH命令後,列表的長度。
*/
public Long lPush(String key,Collection<Object> values) {
return redisTemplate.opsForList().leftPushAll(key,values);
}
/**
* 實現命令 : LPUSHX key 元素
* key 存在時在,最左端推入元素
*
* @param key
* @param value
* @return 執行 LPUSHX 命令後,列表的長度。
*/
public Long lPushX(String key,Object value) {
return redisTemplate.opsForList().leftPushIfPresent(key,value);
}
/**
* 實現命令 : RPUSH key 元素1 [元素2 ...]
* 在最右端推入元素
*
* @param key
* @param values
* @return 執行 RPUSH 命令後,列表的長度。
*/
public Long rPush(String key,Collection<Object> values) {
return redisTemplate.opsForList().rightPushAll(key,values);
}
/**
* 實現命令 : RPUSHX key 元素
* key 存在時,在最右端推入元素
*
* @param key
* @param value
* @return 執行 RPUSHX 命令後,列表的長度。
*/
public Long rPushX(String key,Object value) {
return redisTemplate.opsForList().rightPushIfPresent(key,value);
}
/************************************************* List 相關操作 ***************************************************/
/************************************************** SET 相關操作 ***************************************************/
/**
* 實現命令 : SADD key member1 [member2 ...]
* 新增成員
*
* @param key
* @param values
* @return 新增成功的個數
*/
public Object rPopLpush(String key,Collection<Object> values) {
Object[] members = values.toArray();
return redisTemplate.opsForSet().add(key,members);
}
/**
* 實現命令 : SREM key member1 [member2 ...]
* 刪除指定的成員
*
* @param key
* @param values
* @return 刪除成功的個數
*/
public Long sRem(String key,Collection<Object> values) {
Object[] members = values.toArray();
return redisTemplate.opsForSet().remove(key,members);
}
/**
* 實現命令 : SDIFF key [otherKey ...]
* 求 key 的差集
*
* @param key
* @param otherKeys
* @return
*/
public Set<Object> sDiff(String key,List<String> otherKeys) {
return redisTemplate.opsForSet().difference(key,otherKeys);
}
/**
* 實現命令 : SDIFFSTORE 目標key key [otherKey ...]
* 儲存 key 的差集
*
* @param targetKey 目標key
* @param key
* @param otherKeys
* @return
*/
public Long sDiffStore(String targetKey,List<String> otherKeys) {
return redisTemplate.opsForSet().differenceAndStore(key,otherKeys,List<String> otherKeys) {
return redisTemplate.opsForSet().intersect(key,otherKeys);
}
/**
* 實現命令 : SINTERSTORE 目標key key [otherKey ...]
* 儲存 key 的交集
*
* @param targetKey 目標key
* @param key
* @param otherKeys
* @return
*/
public Long sInterStore(String targetKey,List<String> otherKeys) {
return redisTemplate.opsForSet().intersectAndStore(key,List<String> otherKeys) {
return redisTemplate.opsForSet().union(key,otherKeys);
}
/**
* 實現命令 : SUNIONSTORE 目標key key [otherKey ...]
* 儲存 key 的並集
*
* @param targetKey 目標key
* @param key
* @param otherKeys
* @return
*/
public Long sUnionStore(String targetKey,List<String> otherKeys) {
return redisTemplate.opsForSet().unionAndStore(key,targetKey);
}
/************************************************** SET 相關操作 ***************************************************/
/*********************************************** Sorted SET 相關操作 ***********************************************/
/**
* 實現命令 : ZADD key score1 member1 [score2 member2 ...]
* 批量新增 成員/分數 對
*
* @param key
* @param tuples
* @return
*/
public Long zAdd(String key,Set<ZSetOperations.TypedTuple<Object>> tuples) {
return redisTemplate.opsForZSet().add(key,tuples);
}
/**
* 實現命令 : ZREM key member [member ...]
* 刪除成員
*
* @param key
* @param values
* @return
*/
public Long zRem(String key,Collection<Object> values) {
Object[] members = values.toArray();
return redisTemplate.opsForZSet().remove(key,members);
}
/**
* 實現命令 : ZUNIONSTORE destination numkeys key1 [key2 ...]
* 計算指定key集合與otherKey集合的並集,並儲存到targetKey集合,aggregat 預設為 SUM
*
* @param targetKey 目標集合
* @param key 指定集合
* @param otherKey 其他集合
* @return
*/
public Long zUnionStore(String targetKey,String otherKey) {
return redisTemplate.opsForZSet().unionAndStore(key,otherKey,targetKey);
}
/**
* 實現命令 : ZUNIONSTORE destination numkeys key1 [key2 ...]
* 計算指定key集合與otherKey集合的並集,並儲存到targetKey集合,aggregat 預設為 SUM
*
* @param targetKey 目標集合
* @param key 指定集合
* @param otherKeys 其他集合
* @return
*/
public Long zUnionStore(String targetKey,Collection<String> otherKeys) {
return redisTemplate.opsForZSet().unionAndStore(key,targetKey);
}
/**
* 實現命令 : ZUNIONSTORE destination numkeys key1 [key2 ...][AGGREGATE SUM | MIN | MAX]
* 計算指定key集合與otherKey集合的並集,並儲存到targetKey集合
*
* @param targetKey 目標集合
* @param key 指定集合
* @param otherKeys 其他集合
* @param aggregat SUM 將同一成員的分數相加,MIN 取同一成員中分數最小的,MAX 取同一成員中分數最大的
* @return
*/
public Long zUnionStore(String targetKey,Collection<String> otherKeys,RedisZSetCommands.Aggregate aggregat) {
return redisTemplate.opsForZSet().unionAndStore(key,aggregat);
}
/**
* 實現命令 : ZINTERSTORE destination numkeys key1 [key2 ...]
* 計算指定key集合與otherKey集合的交集,並儲存到targetKey集合,aggregat 預設為 SUM
*
* @param targetKey 目標集合
* @param key 指定集合
* @param otherKey 其他集合
* @return
*/
public Long zInterStore(String targetKey,String otherKey) {
return redisTemplate.opsForZSet().intersectAndStore(key,targetKey);
}
/**
* 實現命令 : ZINTERSTORE destination numkeys key1 [key2 ...]
* 計算指定key集合與otherKey集合的交集,並儲存到targetKey集合,aggregat 預設為 SUM
*
* @param targetKey 目標集合
* @param key 指定集合
* @param otherKeys 其他集合
* @return
*/
public Long zInterStore(String targetKey,targetKey);
}
/**
* 實現命令 : ZINTERSTORE destination numkeys key1 [key2 ...][AGGREGATE SUM | MIN | MAX]
* 計算指定key集合與otherKey集合的交集,並儲存到targetKey集合
*
* @param targetKey 目標集合
* @param key 指定集合
* @param otherKeys 其他集合
* @param aggregat SUM 將同一成員的分數相加,MAX 取同一成員中分數最大的
* @return
*/
public Long zInterStore(String targetKey,aggregat);
}
/*********************************************** Sorted SET 相關操作 ***********************************************/
}
複製程式碼
番外
雖然上面的自定義 Redis 操作類,都是對 RedisTemplate 的簡單封裝,但在簡單的事情,只要你認真做也會有收穫。
比如說,我在封裝 RedisTemplate 的過程中,發現 RedisTemplate 的有些方法的表述與方法的作用不一致,也就是說官方的方法描述寫錯了。於是我 Fork 了一份 spring-data-redis ,修改了錯誤的描述後,Pull Requests,等待官方合併,出乎意料的是官方很快合併了該請求,前後不到2天。
也算是為 spring 專案做了一點微小的貢獻吧!
通過這件事,我發現給開源專案做貢獻,沒有想象中的那麼難,最困難的可能是如果踏出第一步。之後我會被整個過程寫成詳細的教程供大家參考。