在日常开发中,Redis 几乎成了我们提升系统性能的“标配”。缓存热点数据、分布式锁、限流……样样不落。
但随着项目越来越复杂,直接在业务代码中调用 StringRedisTemplate
会让代码变得又臭又长,难以维护。
所以,我们需要一个“高内聚、低耦合”的 Redis 工具类,来解耦 Redis 操作。
今天这篇文章,我们就一起来封装一个通用的 Redis 工具类,并聊聊其中的设计思路。
🧱项目背景
我们使用 Spring Boot 框架,Redis 客户端是 Spring 提供的 StringRedisTemplate
,序列化和反序列化用的是 Hutool
工具包(你也可以换成 Jackson / FastJSON / Gson)。
最终的效果是:
// 存对象
cacheUtils.add("user:1001", new User("张三", 18));
// 获取对象
User user = cacheUtils.getObject("user:1001", User.class);
是不是比直接操作 Redis 更清爽?
🔧工具类源码详解
我们先来看代码,再逐段解析思路。
@Slf4j
@Component
public class CacheUtils {
@Autowired(required = false)
StringRedisTemplate redisTemplate;
final String DEFAULT_KEY_PREFIX = "";
final int EXPIRE_TIME = 6;
final TimeUnit EXPIRE_TIME_TYPE = TimeUnit.HOURS;
✅ 说明:
- 使用了
@Component
注解,Spring 会自动注入。 - 通过
@Autowired(required = false)
注入 RedisTemplate(防止 Redis 没配置时启动报错)。 - 设置了默认的 key 前缀(用于统一管理缓存命名空间)。
- 设置了默认的过期时间为 6 小时(可在方法中自定义覆盖)。
1️⃣ 添加缓存
public <K,V> void add(K key, V value) {
try {
if (value != null) {
redisTemplate.opsForValue().set(DEFAULT_KEY_PREFIX + key,
JSONUtil.toJsonStr(value), EXPIRE_TIME, EXPIRE_TIME_TYPE);
}
} catch (Exception e) {
log.debug(e.getMessage(), e);
throw new RuntimeException("数据缓存至redis失败");
}
}
你也可以自定义过期时间:
public <K,V> void add(K key, V value, Integer expireTime, TimeUnit timeUnit) {
try {
if (value != null) {
redisTemplate.opsForValue().set(DEFAULT_KEY_PREFIX + key,
JSONUtil.toJsonStr(value), expireTime, timeUnit);
}
} catch (Exception e) {
log.debug(e.getMessage(), e);
throw new RuntimeException("数据缓存至redis失败");
}
}
🎯 亮点:
- 泛型
<K, V>
支持任意 key 和 value 类型。 - 通过
JSONUtil.toJsonStr()
实现对象转 JSON 存储。 - 提供了默认过期时间和自定义过期时间两个方法,灵活性满分。
2️⃣ 获取缓存(字符串形式)
public <K> String get(K key){
String value = null;
try{
value = redisTemplate.opsForValue().get(DEFAULT_KEY_PREFIX + key);
if("null".equals(value)) {
return null;
}
} catch (Exception e) {
log.debug(e.getMessage(), e);
}
return value;
}
3️⃣ 获取缓存(对象反序列化)
public <K, V> V getObject(K key, Class<V> clazz) {
String value = this.get(key);
V result = null;
if (!StringUtils.isEmpty(value)) {
result = JSONUtil.toBean(value, clazz);
}
return result;
}
🎯 亮点:
getObject
方法封装了取值 + 反序列化两个步骤。- 避免业务层写重复代码,代码更清晰简洁。
💡优化建议
虽然当前这个工具类已经能应付日常开发了,但还是有一些可以进一步优化的地方:
✅ 添加方法泛型增强
目前 add
方法没有返回值,我们可以考虑返回 boolean
表示是否写入成功。
✅ key 统一前缀命名空间
建议将 DEFAULT_KEY_PREFIX
设置为项目级前缀,例如 "pzforest:"
,避免 Redis 污染。
final String DEFAULT_KEY_PREFIX = "pzforest:";
✅ 添加删除缓存方法
public <K> void delete(K key) {
redisTemplate.delete(DEFAULT_KEY_PREFIX + key);
}
🧪实战演示
// 写入用户信息到缓存
User user = new User("张三", 18);
cacheUtils.add("user:1001", user, 2, TimeUnit.HOURS);
// 读取用户信息
User cachedUser = cacheUtils.getObject("user:1001", User.class);
System.out.println(cachedUser.getName()); // 张三
🧠写在最后
封装 Redis 工具类的目的,就是让“缓存”这种横切逻辑和业务代码解耦,让我们关注业务本身。
你可以根据项目需求,继续封装更多操作,比如:
- 缓存空值防击穿
- 分布式锁(基于 setnx)
- 缓存预热、延迟双删
希望这篇文章对你有帮助,欢迎点赞、收藏、评论交流!
👨💻 作者:一个爱封装工具类的程序员
📬 欢迎关注我,带你写出优雅的 Java 后端代码!
如果你希望我也帮你写文章中的代码注释、文档或 JavaDoc,随时告诉我!