如何优雅地封装缓存工具类?基于RedisTemplate的实践

759 阅读3分钟

在现代分布式系统中,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 工具类的实现有更多疑问或建议,欢迎留言讨论! 😊