search.png
关于我
menu.png
超实用的Redis的工具类

收录于墨的2020~2021开发经验总结

这个工具类最早是在网络上找的,现在已经找不到出处了,后边自己改了很多地方,也加了很多新的东西。

现在将其公开出来,希望对大家有用。

需要导入包:

    compile 'org.springframework.data:spring-data-redis:2.3.2.RELEASE'

maven的话是:

<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.3.2.RELEASE</version>
</dependency>

RedisUtil:


import cn.hengyumo.dawn.utils.JsonUtil;
import cn.hengyumo.dawn.utils.SerializeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * RedisUtil
 * Redis工具类
 *
 * @author hengyumo
 * @since 2019/6/16
 */
@Component
public class RedisUtil {

    // 以下命令删除xxx*格式的所有key值
    private final static String LUA_SCRIPT_CLEAR_WITH_KEY_PRE =
            "local redisKeys = redis.call('keys',KEYS[1]..'*');" +
                    "for i,k in pairs(redisKeys) do redis.call('del',k);end;" +
                    "return redisKeys;";

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @PostConstruct
    public void setSerializer() {
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        RedisSerializer<Object> fastJsonSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(fastJsonSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(fastJsonSerializer);
    }

    public void setJson(String key, String field, Object object) {
        redisTemplate.opsForHash().put(key, field, JsonUtil.jsonString(Objects.requireNonNull(object)));
    }

    public JSONObject getJsonObject(String key, String field) {
        String value = (String) redisTemplate.opsForHash().get(key, field);
        if (value == null) {
            return null;
        }
        return JSON.parseObject(value);
    }

    public Object getJson(String key, String field) {
        String value = (String) redisTemplate.opsForHash().get(key, field);
        if (value == null) {
            return null;
        }
        return JsonUtil.javaObject(value);
    }

    public void setWithSerialize(String key, String field, Object object) {
        redisTemplate.opsForHash().put(key, field,
                Objects.requireNonNull(SerializeUtil.serialize(object)));
    }

    public Object getWithSerialize(String key, String field) {
        byte[] value = (byte[]) redisTemplate.opsForHash().get(key, field);
        if (value == null) {
            return null;
        }
        return SerializeUtil.deserialize(value);
    }

    // Key(键),简单的key-value操作

    /**
     * 实现命令:TTL key,以秒为单位,返回给定 key的剩余生存时间(TTL, time to live)。
     */
    public Long ttl(String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * 实现命令:expire 设置过期时间,单位秒
     */
    public void expire(String key, long timeout) {
        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 实现命令:INCR key,增加key一次
     */
    public Long incr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 实现命令:KEYS pattern,查找所有符合给定模式 pattern的 key
     */
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 实现命令:DEL key,删除一个key
     */
    public void del(String key) {
        redisTemplate.delete(key);
    }

    // String(字符串)

    /**
     * 实现命令:SET key value,设置一个key-value(将字符串值 value关联到 key)
     */
    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 实现命令:SET key value EX seconds,设置key-value和超时时间(秒)
     */
    public void set(String key, String value, long timeoutSecond) {
        if (timeoutSecond <= 0) {
            redisTemplate.opsForValue().set(key, value);
        } else {
            redisTemplate.opsForValue().set(key, value, timeoutSecond, TimeUnit.SECONDS);
        }
    }

    // set key value px expire
    public void setObject(String key, Object value, long expire, TimeUnit timeUnit) {
        if (expire <= 0) {
            redisTemplate.opsForValue().set(key, value);
        } else {
            redisTemplate.opsForValue().set(key, value, expire, timeUnit);
        }
    }

    // get key
    public Object getObject(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    // get key 并获取标识位,标识是否缓存中存在这个Key
    // 该设计是为了避免空值时出现缓存穿透的可能
    public Pair<Boolean, Optional<?>> getObjectWithState(String key) {
        Set<String> keySet = keys(key);
        boolean cacheContainsKey = keySet.contains(key);
        Object value = cacheContainsKey ? redisTemplate.opsForValue().get(key) : null;
        return Pair.of(cacheContainsKey, Optional.ofNullable(value));
    }

    /**
     * 执行 lua 脚本
     * @author hengyumo
     * @since 2021-06-05
     *
     * @param luaScript  lua 脚本
     * @param returnType 返回的结构类型
     * @param keys       KEYS
     * @param argv       ARGV
     * @param <T>        泛型
     *
     * @return 执行的结果
     */
    public <T> T executeLuaScript(String luaScript, Class<T> returnType, String[] keys, String... argv) {
        return redisTemplate.execute(RedisScript.of(luaScript, returnType),
                new StringRedisSerializer(),
                new GenericToStringSerializer<>(returnType),
                Arrays.asList(keys),
                (Object[]) argv);
    }

    /**
     * @author hengyumo
     * @since 2021-06-05
     *
     * 删除以key为前缀的所有键值
     * @param keyPre 前缀
     * @return  返回删除掉的所有key
     */
    public List<String> deleteKeysWithPre(String keyPre) {
        @SuppressWarnings("unchecked")
        List<Object> result = executeLuaScript(LUA_SCRIPT_CLEAR_WITH_KEY_PRE, List.class, new String[] {keyPre});
        return result.stream().map(x -> {
            if (x instanceof List) {
                @SuppressWarnings("unchecked")
                List<String> list = (List<String>) x;
                if (list.size() > 0) {
                    return list.get(0);
                }
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }

    /**
     * 实现命令:GET key,返回 key所关联的字符串值。
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    // Hash(哈希表)

    /**
     * 实现命令:HSET key field value,将哈希表 key中的域 field的值设为 value
     */
    public void hset(String key, String field, Object value) {
        redisTemplate.opsForHash().put(key, field, value);
    }

    /**
     * 实现命令:HGET key field,返回哈希表 key中给定域 field的值
     */
    public String hget(String key, String field) {
        return (String) redisTemplate.opsForHash().get(key, field);
    }

    /**
     * 实现命令:HDEL key field [field ...],删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
     */
    public void hdel(String key, Object... fields) {
        redisTemplate.opsForHash().delete(key, fields);
    }

    /**
     * 实现命令:HGETALL key,返回哈希表 key中,所有的域和值。
     */
    public Map<Object, Object> hgetall(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    // List(列表)

    /**
     * 实现命令:LPUSH key value,将一个值 value插入到列表 key的表头
     */
    public Long lpush(String key, String value) {
        return redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 实现命令:LPOP key,移除并返回列表 key的头元素。
     */
    public Object lpop(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 实现命令:RPUSH key value,将一个值 value插入到列表 key的表尾(最右边)。
     */
    public Long rpush(String key, String value) {
        return redisTemplate.opsForList().rightPush(key, value);
    }
}


版权声明

知识共享许可协议 本文章由作者“衡于墨”创作,转载请注明出处,未经允许禁止用于商业用途

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
发布时间:2021年06月13日 21:29:32

评论区#

还没有评论哦,期待您的评论!

关闭特效