基於 RedisTemplate 自定義 Redis 操做類

歡迎糾錯!!!java

該操做類基於自定義的 RedisTemplate,關於自定義 RedisTemplate,請參考Spring Boot 2.0 集成 redisredis

BaseRedisOperator

該類的設計思路是,與 Redis 命令語法及格式保持一致,以達到使用該類與直接使用 Redis 命令類似的體驗。spring

因爲 Redis 命令衆多,並無實現所有的命令,而是實現了經常使用的大部分命令。安全

封裝好後沒有進行測試,僅供參考 bash

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, ttl, 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, ttl, TimeUnit.SECONDS);
    }


    /**
     * 實現命令 : SET key value PX 毫秒 、 psetex key value 毫秒
     * 添加一個 String 類型的鍵值對,並設置生存時間
     *
     * @param key
     * @param value
     * @param ttl   key 的生存時間,單位:毫秒
     */
    public void set(String key, Object value, long ttl) {
        redisTemplate.opsForValue().set(key, value, ttl, 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, Object value, 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, value, ttl, 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, value, ttl, 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, value, ttl, 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, String field, Object value) {
        Boolean result = redisTemplate.opsForHash().putIfAbsent(key, field, 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, String field, long number) {
        return redisTemplate.opsForHash().increment(key, field, number);
    }


    /**
     * 實現命令 : HINCRBYFLOAT key field 浮點數
     * 給字段的值加上一個浮點數
     *
     * @param key
     * @param field
     * @return 運算後的值
     */
    public Double hInCrByFloat(String key, String field, Double number) {
        return redisTemplate.opsForHash().increment(key, field, 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, timeout, 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, pivot, value);
            default:
                return null;
        }
    }


    /**
     * 實現命令 : LRANGE key 開始下標 結束下標
     * 獲取指定範圍的元素,下標從0開始,包括開始下標,也包括結束下標(待驗證)
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<Object> lRange(String key, int start, int end) {
        return redisTemplate.opsForList().range(key, start, 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 start, int end) {
        redisTemplate.opsForList().trim(key, start, 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, timeout, 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, String targetKey, Object value) {
        Boolean result = redisTemplate.opsForSet().move(sourceKey, value, 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 key, String... otherKeys) {
        List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
        return redisTemplate.opsForSet().intersectAndStore(key, otherKeyList, 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 key, String... otherKeys) {
        List<String> otherKeyList = Stream.of(otherKeys).collect(Collectors.toList());
        return redisTemplate.opsForSet().unionAndStore(key, otherKeyList, 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, value, 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 start, int end) {
        return redisTemplate.opsForZSet().removeRange(key, start, 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, Object value, double delta) {
        return redisTemplate.opsForZSet().incrementScore(key, value, 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 min, double max) {
        return redisTemplate.opsForZSet().count(key, min, 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 start, int end) {
        return redisTemplate.opsForZSet().range(key, start, end);
    }


    /**
     * 實現命令 : ZREVRANGE key start end
     * 獲取 start下標到 end下標之間到成員,並按分數從小到大返回
     * 下標從0開始,支持負下標,-1表示最後一個成員,包括開始下標,也包括結束下標(未驗證)
     *
     * @param key
     * @param start 開始下標
     * @param end   結束下標
     * @return
     */
    public Set<Object> zRevRange(String key, int start, int end) {
        return redisTemplate.opsForZSet().reverseRange(key, start, end);
    }


    /**
     * 實現命令 : ZRANGEBYSCORE key min max
     * 獲取分數範圍內的成員並按從小到大返回
     * (未驗證)
     *
     * @param key
     * @param min 小分數
     * @param max 大分數
     * @return
     */
    public Set<Object> zRangeByScore(String key, double min, double max) {
        return redisTemplate.opsForZSet().rangeByScore(key, min, 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 min, double max, int offset, int count) {
        return redisTemplate.opsForZSet().rangeByScore(key, min, max, offset, count);
    }


    /**
     * 實現命令 : ZREVRANGEBYSCORE key min max
     * 獲取分數範圍內的成員並按從大到小返回
     * (未驗證)
     *
     * @param key
     * @param min 小分數
     * @param max 大分數
     * @return
     */
    public Set<Object> zRevRangeByScore(String key, double min, double max) {
        return redisTemplate.opsForZSet().reverseRangeByScore(key, min, 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, double min, double max, int offset, int count) {
        return redisTemplate.opsForZSet().reverseRangeByScore(key, min, max, offset, count);
    }

    /*********************************************** Sorted SET 相關操做 ***********************************************/

}
複製代碼

RedisOperator

RedisOperator 類在 BaseRedisOperator 的基礎上補充了一下沒法按照 Redis 命令 設計的類。app

使用該類並不會給你帶來相似直接使用Redis 命令的體驗dom

封裝好後沒有進行測試,僅供參考 post

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 date) {
        Boolean result = redisTemplate.expireAt(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, String key, List<String> otherKeys) {
        return redisTemplate.opsForSet().differenceAndStore(key, otherKeys, targetKey);
    }


    /**
     * 實現命令 : SINTER key [otherKey ...]
     * 求 key 的交集
     *
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<Object> sInter(String key, 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, String key, List<String> otherKeys) {
        return redisTemplate.opsForSet().intersectAndStore(key, otherKeys, targetKey);
    }


    /**
     * 實現命令 : SUNION key [otherKey ...]
     * 求 key 的並集
     *
     * @param key
     * @param otherKeys
     * @return
     */
    public Set<Object> sUnion(String 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, String key, List<String> otherKeys) {
        return redisTemplate.opsForSet().unionAndStore(key, otherKeys, 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 key, 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, String key, Collection<String> otherKeys) {
        return redisTemplate.opsForZSet().unionAndStore(key, otherKeys, 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, String key, Collection<String> otherKeys, RedisZSetCommands.Aggregate aggregat) {
        return redisTemplate.opsForZSet().unionAndStore(key, otherKeys, targetKey, aggregat);
    }


    /**
     * 實現命令 : ZINTERSTORE destination numkeys key1 [key2 ...]
     * 計算指定key集合與otherKey集合的交集,並保存到targetKey集合,aggregat 默認爲 SUM
     *
     * @param targetKey 目標集合
     * @param key       指定集合
     * @param otherKey  其餘集合
     * @return
     */
    public Long zInterStore(String targetKey, String key, String otherKey) {
        return redisTemplate.opsForZSet().intersectAndStore(key, otherKey, targetKey);
    }


    /**
     * 實現命令 : ZINTERSTORE destination numkeys key1 [key2 ...]
     * 計算指定key集合與otherKey集合的交集,並保存到targetKey集合,aggregat 默認爲 SUM
     *
     * @param targetKey 目標集合
     * @param key       指定集合
     * @param otherKeys 其餘集合
     * @return
     */
    public Long zInterStore(String targetKey, String key, Collection<String> otherKeys) {
        return redisTemplate.opsForZSet().unionAndStore(key, otherKeys, targetKey);
    }


    /**
     * 實現命令 : ZINTERSTORE 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 zInterStore(String targetKey, String key, Collection<String> otherKeys, RedisZSetCommands.Aggregate aggregat) {
        return redisTemplate.opsForZSet().unionAndStore(key, otherKeys, targetKey, aggregat);
    }

    /*********************************************** Sorted SET 相關操做 ***********************************************/
}
複製代碼

番外

雖然上面的自定義 Redis 操做類,都是對 RedisTemplate 的簡單封裝,但在簡單的事情,只要你認真作也會有收穫。測試

好比說,我在封裝 RedisTemplate 的過程當中,發現 RedisTemplate 的有些方法的表述與方法的做用不一致,也就是說官方的方法描述寫錯了。因而我 Fork 了一份 spring-data-redis ,修改了錯誤的描述後,Pull Requests,等待官方合併,出乎意料的是官方很快合併了該請求,先後不到2天。ui

也算是爲 spring 項目作了一點微小的貢獻吧!

經過這件事,我發現給開源項目作貢獻,沒有想象中的那麼難,最困難的多是若是踏出第一步。以後我會被整個過程寫成詳細的教程供你們參考。

如何給開源項目貢獻代碼,以spring爲例

相關文章
相關標籤/搜索