在 Spring Boot 项目中使用 Redis 是非常常见的需求。
为了提高开发效率和代码复用性,我们通常会封装一个 Redis 工具类,用于统一管理各种 Redis 操作。
本文将带你一步步实现一个完善的 生产级增强版本 Redis 工具类封装,涵盖企业级开发所需的常用功能,支持:
- 🔹 Key-Value 存取
- 🔹 批量删除、存在检测
- 🔹 过期时间管理
- 🔹 Hash / List / Set / ZSet 操作
- 🔹 自增、自减等常见功能
- 🔹 对象 JSON 序列化(避免乱码)
- 🔹 泛型封装(避免强制类型转换)
- 🔹 分布式锁(防止并发操作冲突)
🧭 目录
一、项目依赖
在 pom.xml 中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
二、Redis 序列化配置
建议不要使用默认的 JDK 序列化,会导致乱码和体积膨胀。
我们改用GenericJackson2JsonRedisSerializer,可序列化对象为 JSON 格式。
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用 Jackson 序列化(替代默认 JDK 序列化)
GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
StringRedisSerializer stringSerializer = new StringRedisSerializer();
// Key & HashKey
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
// Value & HashValue
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
template.afterPropertiesSet();
return template;
}
}
三、Redis 工具类封装(增强版)
package com.example.demo.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// ============================= 通用 Key 操作 =============================
/** 设置过期时间 */
public boolean expire(String key, long time) {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
return true;
}
return false;
}
/** 获取过期时间(单位:秒) */
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/** 判断 Key 是否存在 */
public boolean hasKey(String key) {
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}
/** 删除一个或多个 Key */
public void del(String... keys) {
if (keys != null && keys.length > 0) {
if (keys.length == 1) redisTemplate.delete(keys[0]);
else redisTemplate.delete(Arrays.asList(keys));
}
}
// ============================= String 操作 =============================
/** 获取值(泛型) */
@SuppressWarnings("unchecked")
public <T> T get(String key, Class<T> clazz) {
Object obj = redisTemplate.opsForValue().get(key);
return obj == null ? null : (T) obj;
}
/** 设置值 */
public boolean set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
return true;
}
/** 设置值并指定过期时间 */
public boolean set(String key, Object value, long seconds) {
redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
return true;
}
/** 递增操作 */
public long incr(String key, long delta) {
if (delta < 0) throw new IllegalArgumentException("递增因子必须大于0");
return redisTemplate.opsForValue().increment(key, delta);
}
/** 递减操作 */
public long decr(String key, long delta) {
if (delta < 0) throw new IllegalArgumentException("递减因子必须大于0");
return redisTemplate.opsForValue().increment(key, -delta);
}
// ============================= Hash 操作 =============================
/** 获取指定字段 */
public Object hGet(String key, String field) {
return redisTemplate.opsForHash().get(key, field);
}
/** 获取全部字段 */
public Map<Object, Object> hGetAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
/** 设置多个字段 */
public void hSetAll(String key, Map<String, Object> map) {
redisTemplate.opsForHash().putAll(key, map);
}
/** 设置单个字段 */
public void hSet(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
/** 删除字段 */
public void hDel(String key, Object... fields) {
redisTemplate.opsForHash().delete(key, fields);
}
// ============================= Set 操作 =============================
public long sAdd(String key, Object... values) {
return redisTemplate.opsForSet().add(key, values);
}
public Set<Object> sMembers(String key) {
return redisTemplate.opsForSet().members(key);
}
public boolean sIsMember(String key, Object value) {
return Boolean.TRUE.equals(redisTemplate.opsForSet().isMember(key, value));
}
public long sSize(String key) {
return redisTemplate.opsForSet().size(key);
}
public long sRemove(String key, Object... values) {
return redisTemplate.opsForSet().remove(key, values);
}
// ============================= List 操作 =============================
public long lPush(String key, Object value) {
return redisTemplate.opsForList().leftPush(key, value);
}
public long rPush(String key, Object value) {
return redisTemplate.opsForList().rightPush(key, value);
}
public Object lPop(String key) {
return redisTemplate.opsForList().leftPop(key);
}
public Object rPop(String key) {
return redisTemplate.opsForList().rightPop(key);
}
public List<Object> lRange(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
// ============================= ZSet 操作 =============================
public boolean zAdd(String key, Object value, double score) {
return Boolean.TRUE.equals(redisTemplate.opsForZSet().add(key, value, score));
}
public Set<Object> zRange(String key, long start, long end) {
return redisTemplate.opsForZSet().range(key, start, end);
}
public long zRemove(String key, Object... values) {
return redisTemplate.opsForZSet().remove(key, values);
}
// ============================= 分布式锁 =============================
/**
* 尝试获取分布式锁
* @param key 锁名称
* @param value 唯一标识(如UUID)
* @param expireSeconds 锁过期时间(防止死锁)
*/
public boolean tryLock(String key, String value, long expireSeconds) {
Boolean success = redisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofSeconds(expireSeconds));
return Boolean.TRUE.equals(success);
}
/**
* 释放分布式锁(需校验锁标识)
*/
public boolean unlock(String key, String value) {
Object cachedValue = redisTemplate.opsForValue().get(key);
if (value.equals(cachedValue)) {
redisTemplate.delete(key);
return true;
}
return false;
}
}
四、功能分类详解
| 分类 | 方法 | 功能描述 |
|---|---|---|
| Key 管理 | expire, hasKey, del | 设置/检测/删除 key |
| String 操作 | get, set, incr, decr | 基础 KV |
| Hash 操作 | hGet, hSet, hGetAll, hDel | 对象型数据 |
| Set 操作 | sAdd, sMembers, sIsMember | 无序去重集合 |
| List 操作 | lPush, rPush, lRange | 队列/消息列表 |
| ZSet 操作 | zAdd, zRange, zRemove | 排行榜/权重数据 |
| 分布式锁 | tryLock, unlock | 控制并发写入,防止重复执行 |
五、分布式锁机制
分布式锁常见用法如下:
String lockKey = "order:create:lock";
String lockValue = UUID.randomUUID().toString();
boolean locked = redisUtils.tryLock(lockKey, lockValue, 10);
if (locked) {
try {
// 执行业务逻辑
} finally {
redisUtils.unlock(lockKey, lockValue);
}
}
✅ 使用
setIfAbsent()+ 过期时间,可防止死锁。
⚠️ 一定要在释放锁时校验 value,避免误删其他线程的锁。
六、使用示例
@Autowired
private RedisUtils redisUtils;
// 设置字符串
redisUtils.set("user:name", "Simon", 3600);
String name = redisUtils.get("user:name", String.class);
// Hash
redisUtils.hSet("user:1001", "age", 28);
Map<Object, Object> userMap = redisUtils.hGetAll("user:1001");
// List
redisUtils.rPush("log:list", "事件A");
redisUtils.rPush("log:list", "事件B");
List<Object> logs = redisUtils.lRange("log:list", 0, -1);
// 分布式锁
String lockVal = UUID.randomUUID().toString();
if (redisUtils.tryLock("job:sync", lockVal, 5)) {
try {
// 执行任务
} finally {
redisUtils.unlock("job:sync", lockVal);
}
}
764

被折叠的 条评论
为什么被折叠?



