在现代分布式系统中,Redis 作为一种高性能的键值存储系统,广泛应用于缓存、分布式锁、消息队列等场景。为了简化 Redis 的使用,我们通常会对其进行封装,提供一个统一的工具类。本文将介绍如何借助HuTool工具类(StrUtil,CollUtil)与( org.springframework.data.redis.core.RedisTemplate )来封装 Redis 工具类,并分享一些关键功能的实现。
1. 工具类设计目标
- 简化操作:封装 Redis 的常用操作,如缓存设置、获取、删除等。
- 异常处理:统一处理 Redis 操作中的异常,避免代码冗余。
- 原子性操作:支持原子性操作,如比较并删除(CAD)。
- 批量操作:支持批量删除缓存,提高操作效率。
2. 工具类核心功能
2.1 缓存失效时间设置
public static Boolean expire(String key, long time) {
if (key.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
try {
if (time > 0) {
REDIS_TEMPLATE.expire(key, time, TimeUnit.SECONDS);
}
return Boolean.TRUE;
} catch (Exception e) {
logger.error("Set expire error: {}", e.getMessage());
return Boolean.FALSE;
}
}
- 功能:为指定键设置缓存失效时间。
- 异常处理:捕获 Redis 操作异常并记录日志。
2.2 获取缓存失效时间
public static Long getExpire(String key) {
if (key.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
return REDIS_TEMPLATE.getExpire(key, TimeUnit.SECONDS);
}
- 功能:获取指定键的缓存失效时间。
- 返回值:返回失效时间(秒),-1 表示永久有效,0 表示未设置失效时间。
2.3 判断键是否存在
public static Boolean hasKey(String key) {
if (key.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
try {
return REDIS_TEMPLATE.hasKey(key);
} catch (Exception e) {
logger.error("Error getting hasKey: {}", e.getMessage());
return Boolean.FALSE;
}
}
- 功能:判断指定键是否存在。
- 返回值:存在返回
true,否则返回false。
2.4 删除缓存
public static void del(String... key) {
if (key != null && key.length > 0) {
for (String s : key) {
if (s.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
}
if (key.length == 1) {
REDIS_TEMPLATE.delete(key[0]);
} else {
REDIS_TEMPLATE.delete(Arrays.asList(key));
}
}
}
- 功能:删除一个或多个缓存键。
- 批量删除:支持批量删除操作。
2.5 普通缓存获取与设置
public static <T> T get(String key) {
if (key.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
return (T) REDIS_TEMPLATE.opsForValue().get(key);
}
public static boolean set(String key, Object value, long time) {
if (key.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
try {
if (time > 0) {
REDIS_TEMPLATE.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
REDIS_TEMPLATE.opsForValue().set(key, value);
}
return true;
} catch (Exception e) {
logger.error("Redis opsForValue error: {}", e.getMessage());
return false;
}
}
- 功能:获取和设置缓存值。
- 支持过期时间:可以为缓存设置过期时间。
2.6 原子性操作:比较并删除(CAD)
public static boolean cad(String key, String value) {
if (key.contains(StrUtil.SPACE) || value.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Long result = STRING_REDIS_TEMPLATE.execute(new DefaultRedisScript<Long>(script, Long.class),
Collections.singletonList(key), value);
return !Objects.equals(result, 0L);
}
- 功能:比较缓存中的值与给定值,如果相等则删除缓存。
- 原子性:通过 Lua 脚本实现原子性操作。
2.7 批量删除缓存
public static void deleteBatch(List<String> keys) {
if (CollUtil.isEmpty(keys)) {
return;
}
for (String key : keys) {
if (key.contains(StrUtil.SPACE)) {
throw new ExampleProjectException(ResponseEnum.EXCEPTION);
}
}
REDIS_TEMPLATE.delete(keys);
}
- 功能:批量删除缓存键。
- 适用场景:清理多个缓存键时使用。
3. 工具类的优势
- 简化开发:通过封装常用操作,减少重复代码。
- 提高可维护性:统一异常处理和日志记录,便于排查问题。
- 增强功能:支持原子性操作和批量操作,满足复杂业务需求。
4. 总结
通过封装 Redis 工具类,我们可以更高效地使用 Redis,同时提高代码的可读性和可维护性。本文介绍的 Redis 工具类涵盖了缓存设置、获取、删除、原子性操作等核心功能,适用于大多数业务场景。希望本文能为你的 Redis 使用提供参考和帮助!
如果你对 Redis 工具类的实现有更多疑问或建议,欢迎留言讨论! 😊