Redis工具类

本文详细介绍了RedisTemplate在日常开发中对Redis各种数据类型(如字符串、哈希、列表、集合和有序集合)的操作,以及如何使用工具类进行缓存管理,包括基础对象缓存、Map缓存、时间过期和分页查询等。
摘要由CSDN通过智能技术生成

目录

前言

工具类

总结

前言

在日常开发中,对redis的使用还是比较频繁的,为此我总结了一下RedisTemplate的常见操作。

一、redis的数据类型

其实操作redis说到底就是对他的数据类型操作,Redis常用的数据类型有:字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set)。

  1. 字符串(String):最基本的数据类型,可以存储任意类型的字符串,包括整数和浮点数。

  2. 哈希(Hash):类似于关联数组,可以存储多个字段和值的映射关系。

  3. 列表(List):一个有序的字符串列表,可以进行插入和删除操作,还可以使用索引获取元素。

  4. 集合(Set):一个无序的字符串集合,每个元素都是唯一的,可以进行添加、删除和判断成员操作。

  5. 有序集合(Sorted Set):类似于集合,每个成员都关联一个分数(score),根据分数可以进行排序,可以进行添加、删除和查询操作。

这些数据类型都是在内存中存储的,所以具有高效的读写性能。同时,它们都支持一些常用的操作,如增加、删除、修改和查询等。除此之外,Redis还提供了一些特殊的操作,如发布订阅、事务和持久化等,使其更加强大和灵活。

二、工具类

@Component
public class RedisCache {
    @Resource
    public RedisTemplate redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     * @return 缓存的对象
     */
    public <T> ValueOperations<String, T> setCacheObject(String key, T value) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value);
        return operation;
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key      缓存的键值
     * @param value    缓存的值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     * @return 缓存的对象
     */
    public <T> ValueOperations<String, T> setCacheObject(String key, T value, Integer timeout, TimeUnit timeUnit) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        operation.set(key, value, timeout, timeUnit);
        return operation;
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(String key) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public void deleteObject(String key) {
        redisTemplate.delete(key);
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     * @return
     */
    public <T> HashOperations<String, String, T> setCacheMap(String key, Map<String, T> dataMap) {
        HashOperations hashOperations = redisTemplate.opsForHash();
        if (null != dataMap) {
            for (Map.Entry<String, T> entry : dataMap.entrySet()) {
                hashOperations.put(key, ConstantsCache.CACHE_KEY_PRE + entry.getKey(), entry.getValue());
            }
        }
        return hashOperations;
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(String key) {
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        Map<String, T> map = redisTemplate.opsForHash().entries(key);
        return map;
    }

    /**
     * 获取存储在哈希表中指定字段的值
     *
     * @param key
     * @param field
     * @return
     */
    public String getCacheMapValueString(String key, String field) {
        if (!hasKey(key)) {
            return null;
        }
        String preField = ConstantsCache.CACHE_KEY_PRE + field;
        Object obj = redisTemplate.opsForHash().get(key, preField);
        if (obj != null) {
            return obj.toString();
        }
        return "";
    }

    public Object getCacheMapValueObj(String key, String field) {
        if (!hasKey(key)) {
            return null;
        }
        String preField = ConstantsCache.CACHE_KEY_PRE + field;
        Object obj = redisTemplate.opsForHash().get(key, preField);
        return obj;
    }


    /**
     * 获取存储在哈希表中指定字段的值
     *
     * @param key
     * @param field
     * @return
     */
    public <T> T getCacheMapValueJson(String key, String field, Class<T> clazz) {
        if (!hasKey(key)) {
            return null;
        }
        String preField = ConstantsCache.CACHE_KEY_PRE + field;
        Object obj = redisTemplate.opsForHash().get(key, preField);
        if (obj != null) {
            return JSON.parseObject(obj.toString(), clazz);
        }
        return null;
    }

    public Map<String, String> getCacheMapScan(String key, String field) {
        String preField = ConstantsCache.CACHE_KEY_PRE + field;
        Map<String, String> map = new HashMap<>();
        Cursor<Map.Entry<Object,Object>> scan = redisTemplate.opsForHash().scan(key, ScanOptions.scanOptions().match(preField + "*").build());
        while(scan.hasNext()) {
            Map.Entry<Object,Object> entry = scan.next();
            map.put(entry.getKey().toString(), entry.getValue().toString());
        }
        return map;
    }

    /**
     * 模糊查找
     * @param key
     * @param field
     * @return
     */
    public String getCacheMapScanOne(String key, String field) {
        String preField = ConstantsCache.CACHE_KEY_PRE + field;
        Cursor<Map.Entry<Object,Object>> scan = redisTemplate.opsForHash().scan(key, ScanOptions.scanOptions().match(preField + "*").build());
        while(scan.hasNext()) {
            Map.Entry<Object,Object> entry = scan.next();
            return entry.getValue().toString();
        }
        return "";
    }

    public <T> List<T> getCacheMapValueScan(String key, String field, Class<T> clazz) {
        String preField = ConstantsCache.CACHE_KEY_PRE + field;
        List<T> dataList = new ArrayList<T>();
        Cursor<Map.Entry<Object,Object>> scan = redisTemplate.opsForHash().scan(key, ScanOptions.scanOptions().match(preField + "*").build());
        while(scan.hasNext()) {
            Map.Entry<Object,Object> entry = scan.next();
            dataList.add(JSON.parseObject(entry.getValue().toString(), clazz));
        }
        return dataList;
    }
    /**
     * 删除HASH中指定key
     *
     * @param key
     * @param field
     */
    public void deleteMapKey(String key, String field) {
        String preField = ConstantsCache.CACHE_KEY_PRE + field;
        redisTemplate.opsForHash().delete(key, preField);
    }

    /**
     * 是否存在key
     *
     * @param key
     * @return
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 获得缓存的基本对象列表
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }

    /**
     * 获得key的数据类型
     *
     * @param key Redis键
     * @return 数据类型
     */
    public DataType keyType(String key) {
        return redisTemplate.type(key);
    }

    /**
     * 根据条件分页查询Redis键集合
     *
     * @param keyPattern 查询条件
     * @param pageNum    页码
     * @param pageSize   页大小
     * @return 键集合
     * @throws IOException
     */
    public List<String> getPageKeys(String keyPattern, int pageNum, int pageSize) {
        List<String> keys = new ArrayList<>();
        try {
            // 设置分页查询的起始位置
            int startIndex = (pageNum - 1) * pageSize;
            // 使用 SCAN 命令进行分页遍历,并加入 MATCH 选项进行键的匹配
            Cursor<byte[]> cursor = (Cursor<byte[]>) redisTemplate.execute((RedisCallback<Cursor<byte[]>>) connection -> {
                ScanOptions scanOptions = null;
                if (StringUtil.isNotEmpty(keyPattern)) {
                    scanOptions = ScanOptions.scanOptions().count(pageSize).match(keyPattern).build();
                } else {
                    scanOptions = ScanOptions.scanOptions().count(pageSize).build();
                }
                return connection.scan(scanOptions);
            });
            // 获取指定页码的键值
            int currentIndex = 0;
            while (cursor.hasNext()) {
                byte[] keyBytes = cursor.next();
                String key = new String(keyBytes);

                if (currentIndex >= startIndex) {
                    keys.add(key);
                }
                currentIndex++;
                if (keys.size() == pageSize) {
                    break;  // 达到指定页码的大小,提前结束遍历
                }
            }
            cursor.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return keys;
    }

    /**
     * 获取键总数
     *
     * @param keyPattern 查询条件
     * @return 键总数
     */
    public long getKeyCount(String keyPattern) {
        ScanOptions scanOptions = null;
        if (StringUtil.isNotEmpty(keyPattern)) {
            scanOptions = ScanOptions.scanOptions().count(Integer.MAX_VALUE).match(keyPattern).build();
        } else {
            scanOptions = ScanOptions.scanOptions().count(Integer.MAX_VALUE).build();
        }
        ScanOptions finalScanOptions = scanOptions;
        Long count = (Long) redisTemplate.execute((RedisCallback<Long>) connection -> {
            long totalCount = 0;
            try {
                Cursor<byte[]> cursor = connection.scan(finalScanOptions);
                while (cursor.hasNext()) {
                    cursor.next();
                    totalCount++;
                }
                cursor.close();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            return totalCount;
        });
        return count != null ? count : 0;
    }

    /**
     * 根据条件分页查询Redis hash键值集合
     *
     * @param hashKey      hash键
     * @param fieldPattern hash值中的键
     * @param pageNumber   页码
     * @param pageSize     页大小
     * @return hash键值集合
     */
    public List<Map.Entry<String, String>> getPageHashEntries(String hashKey, String fieldPattern, int pageNumber, int pageSize) {
        List<Map.Entry<String, String>> hashEntries = new ArrayList<>();
        try {
            // 设置分页查询的起始位置
            int startIndex = (pageNumber - 1) * pageSize;
            // 使用 HSCAN 命令进行分页遍历,并加入 MATCH 选项进行字段的匹配
            Cursor<Map.Entry<byte[], byte[]>> cursor = (Cursor<Map.Entry<byte[], byte[]>>) redisTemplate.execute((RedisCallback<Cursor<Map.Entry<byte[], byte[]>>>) connection -> {
                ScanOptions scanOptions = null;
                if (StringUtil.isNotEmpty(fieldPattern)) {
                    scanOptions = ScanOptions.scanOptions().count(pageSize).match(fieldPattern).build();
                } else {
                    scanOptions = ScanOptions.scanOptions().count(pageSize).build();
                }
                return connection.hScan(hashKey.getBytes(), scanOptions);
            });
            // 获取指定页码的Hash字段
            int currentIndex = 0;
            while (cursor.hasNext()) {
                Map.Entry<byte[], byte[]> entry = cursor.next();
                String field = new String(entry.getKey());
                String value = new String(entry.getValue());
                if (currentIndex >= startIndex) {
                    Map.Entry<String, String> hashEntry = new HashMap.SimpleEntry<>(field, value);
                    hashEntries.add(hashEntry);
                }
                currentIndex++;
                if (hashEntries.size() == pageSize) {
                    break;  // 达到指定页码的大小,提前结束遍历
                }
            }
            cursor.close();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return hashEntries;
    }

    /**
     * 根据条件查询Redis hash键值总数
     *
     * @param hashKey      hash键
     * @param fieldPattern hash值中的键
     * @return 总数量
     */
    public long getHashCount(String hashKey, String fieldPattern) {
        ScanOptions scanOptions = null;
        if (StringUtil.isNotEmpty(fieldPattern)) {
            scanOptions = ScanOptions.scanOptions().count(Integer.MAX_VALUE).match(fieldPattern).build();
        } else {
            scanOptions = ScanOptions.scanOptions().count(Integer.MAX_VALUE).build();
        }
        ScanOptions finalScanOptions = scanOptions;
        Long count = (Long) redisTemplate.execute((RedisCallback<Long>) connection -> {
            long totalCount = 0;
            Cursor<Map.Entry<byte[], byte[]>> cursor = connection.hScan(hashKey.getBytes(), finalScanOptions);
            while (cursor.hasNext()) {
                cursor.next();
                totalCount++;
            }
            cursor.close();
            return totalCount;
        });
        return count != null ? count : 0;
    }
}

总结

本文主要总结了使用RedisTemplate常用操作,希望对你有所帮助。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
RedisTemplate是Spring框架提供的一个Redis操作工具类,封装了Redis连接池的操作。在使用Redis的时候,可以通过RedisTemplate对Redis进行操作,包括String、Hash、List、Set、ZSet、HyperLogLog等数据结构的操作。 在使用RedisTemplate进行geo操作时,需要先设置序列化方式为GenericJackson2JsonRedisSerializer,然后通过GeoOperations接口进行操作。GeoOperations包括添加地理位置信息、获取两个位置之间的距离、获取指定位置的附近的其他位置信息等操作。 以下是RedisTemplate工具类的示例代码: ``` @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(lettuceConnectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } } @Service public class RedisGeoService { @Autowired private RedisTemplate<String, Object> redisTemplate; public Object addGeo(String key, GeoLocation<Object> location) { GeoOperations<String, Object> geoOperations = redisTemplate.opsForGeo(); return geoOperations.add(key, location); } public Object getDistance(String key, Object member1, Object member2) { GeoOperations<String, Object> geoOperations = redisTemplate.opsForGeo(); return geoOperations.distance(key, member1, member2); } public Object getRadius(String key, Object member, double radius, Metric metric) { GeoOperations<String, Object> geoOperations = redisTemplate.opsForGeo(); return geoOperations.radius(key, member, new Distance(radius, metric)); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alpaca Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值