Spring 整合 Redis 操作步骤总结
1. 添加依赖
首先,在 pom.xml
文件中添加必要的 Maven 依赖。Redis 相关的依赖包括 Spring Boot 的 Redis 启动器和 fastjson
(如果需要使用 Fastjson 作为序列化工具):
<!-- Spring Boot Redis Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Fastjson (用于 JSON 序列化和反序列化) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
2. 配置 Redis 连接信息
在 application.yml
或 application.properties
中配置 Redis 连接信息。以下是 application.yml
配置示例:
spring:
redis:
host: 127.0.0.1
port: 6379
database: 0
jedis:
pool:
max-active: 20
max-wait: -1
max-idle: 10
min-idle: 0
timeout: 2000
3. 配置 Redis 数据源连接池
如果使用连接池(例如 HikariCP),你可以在 application.yml
中配置数据源连接池的参数。Spring Boot 默认会使用 HikariCP 连接池。
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/easylive?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
pool-name: HikariCPDatasource
minimum-idle: 5
idle-timeout: 180000
maximum-pool-size: 10
auto-commit: true
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
4. 创建 Redis 配置类
在 Spring Boot 中配置 RedisTemplate
和 RedisMessageListenerContainer
。以下是一个基本的 RedisConfig
类,它用于配置 Redis 连接、序列化方式等。
@Configuration
public class RedisConfig<V> {
private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
// 配置 RedisTemplate
@Bean("redisTemplate")
public RedisTemplate<String, V> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, V> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置 key 和 value 的序列化方式
template.setKeySerializer(RedisSerializer.string());
template.setValueSerializer(RedisSerializer.json());
template.setHashKeySerializer(RedisSerializer.string());
template.setHashValueSerializer(RedisSerializer.json());
template.afterPropertiesSet();
return template;
}
// 配置 Redis 消息监听容器
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
5. 使用 RedisTemplate 执行 Redis 操作
RedisTemplate
是 Spring Data Redis 提供的核心工具,用于执行 Redis 操作。以下是如何使用 RedisTemplate
进行 Redis 数据的基本操作。
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 保存数据
public void save(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
// 获取数据
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
// 删除数据
public void delete(String key) {
redisTemplate.delete(key);
}
// 使用 Hash 存储数据
public void saveHash(String hashKey, String key, Object value) {
redisTemplate.opsForHash().put(hashKey, key, value);
}
public Object getHash(String hashKey, String key) {
return redisTemplate.opsForHash().get(hashKey, key);
}
}
6. Fastjson 作为序列化工具(可选)
如果你想使用 Fastjson
作为 Redis 数据的序列化和反序列化工具,可以在 RedisConfig
中配置:
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用 Fastjson 序列化
template.setValueSerializer(new FastJsonRedisSerializer<>(Object.class));
template.setHashValueSerializer(new FastJsonRedisSerializer<>(Object.class));
template.afterPropertiesSet();
return template;
}
7. 配置 Redis 消息监听器(可选)
如果你需要实现 Redis 发布/订阅功能,可以配置 RedisMessageListenerContainer
来监听 Redis 频道。
@Service
public class RedisListenerService {
@Autowired
private RedisMessageListenerContainer container;
public void subscribe(String channel) {
MessageListener listener = message -> {
String messageBody = new String(message.getBody());
System.out.println("Received message: " + messageBody);
};
container.addMessageListener(listener, new ChannelTopic(channel));
}
}
8. Redis 操作的示例
保存数据到 Redis:
redisService.save("username", "john_doe");
获取 Redis 中的数据:
String username = (String) redisService.get("username");
删除 Redis 中的数据:
redisService.delete("username");
9. 总结
通过以上步骤,你已经成功将 Redis 集成到 Spring Boot 项目中,主要包括:
- 配置 Redis 连接和连接池。
- 配置
RedisTemplate
和使用序列化工具(如Fastjson
)。 - 使用
RedisTemplate
执行常见的 Redis 操作(如 set/get)。 - 配置 Redis 消息监听器实现发布/订阅功能(可选)。
此方案提供了高效的 Redis 集成方式,可以支持缓存、消息队列、发布/订阅等常见使用场景。
封装工具类
package com.easylive.redis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Component("redisUtils")
public class RedisUtils<V> {
@Resource
private RedisTemplate<String, V> redisTemplate;
private static final Logger logger = LoggerFactory.getLogger(RedisUtils.class);
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
public void delete(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
}
public V get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, V value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
logger.error("设置redisKey:{},value:{}失败", key, value);
return false;
}
}
public boolean keyExists(String key) {
return redisTemplate.hasKey(key);
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean setex(String key, V value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
logger.error("设置redisKey:{},value:{}失败", key, value);
return false;
}
}
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.MILLISECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public List<V> getQueueList(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
public boolean lpush(String key, V value, Long time) {
try {
redisTemplate.opsForList().leftPush(key, value);
if (time != null && time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public long remove(String key, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, 1, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
public boolean lpushAll(String key, List<V> values, long time) {
try {
redisTemplate.opsForList().leftPushAll(key, values);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public V rpop(String key) {
try {
return redisTemplate.opsForList().rightPop(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public Long increment(String key) {
Long count = redisTemplate.opsForValue().increment(key, 1);
return count;
}
public Long incrementex(String key, long milliseconds) {
Long count = redisTemplate.opsForValue().increment(key, 1);
if (count == 1) {
//设置过期时间1天
expire(key, milliseconds);
}
return count;
}
public Long decrement(String key) {
Long count = redisTemplate.opsForValue().increment(key, -1);
if (count <= 0) {
redisTemplate.delete(key);
}
logger.info("key:{},减少数量{}", key, count);
return count;
}
public Set<String> getByKeyPrefix(String keyPrifix) {
Set<String> keyList = redisTemplate.keys(keyPrifix + "*");
return keyList;
}
public Map<String, V> getBatch(String keyPrifix) {
Set<String> keySet = redisTemplate.keys(keyPrifix + "*");
List<String> keyList = new ArrayList<>(keySet);
List<V> keyValueList = redisTemplate.opsForValue().multiGet(keyList);
Map<String, V> resultMap = keyList.stream().collect(Collectors.toMap(key -> key, value -> keyValueList.get(keyList.indexOf(value))));
return resultMap;
}
public void zaddCount(String key, V v) {
redisTemplate.opsForZSet().incrementScore(key, v, 1);
}
public List<V> getZSetList(String key, Integer count) {
Set<V> topElements = redisTemplate.opsForZSet().reverseRange(key, 0, count);
List<V> list = new ArrayList<>(topElements);
return list;
}
}
这个 RedisUtils
类是一个通用的 Redis 工具类,封装了对 Redis 的常见操作,方便在项目中进行缓存处理、队列操作等。下面详细解释每个方法的功能。
1. delete 方法
public void delete(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
}
- 功能:删除指定的 Redis 键,可以一次删除一个或多个键。
- 参数:
key
:一个或多个 Redis 键名。 - 实现:
- 如果只有一个键,调用
redisTemplate.delete(key[0])
删除该键。 - 如果有多个键,先将它们转换成一个
List
,然后调用redisTemplate.delete()
删除多个键。
- 如果只有一个键,调用
2. get 方法
public V get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
- 功能:从 Redis 中获取指定键的值。
- 参数:
key
:Redis 键名。 - 返回:键对应的值,如果键为空则返回
null
。 - 实现:调用
redisTemplate.opsForValue().get(key)
获取 Redis 中保存的值。
3. set 方法
public boolean set(String key, V value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
logger.error("设置redisKey:{},value:{}失败", key, value);
return false;
}
}
- 功能:将数据保存到 Redis 中,使用键值对存储。
- 参数:
key
:Redis 键名,value
:要保存的值。 - 返回:如果成功保存,返回
true
,否则返回false
。 - 实现:调用
redisTemplate.opsForValue().set(key, value)
保存数据,如果发生异常则返回false
并记录日志。
4. keyExists 方法
public boolean keyExists(String key) {
return redisTemplate.hasKey(key);
}
- 功能:检查 Redis 中是否存在指定的键。
- 参数:
key
:Redis 键名。 - 返回:如果键存在返回
true
,否则返回false
。 - 实现:调用
redisTemplate.hasKey(key)
检查键是否存在。
5. setex 方法
public boolean setex(String key, V value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
logger.error("设置redisKey:{},value:{}失败", key, value);
return false;
}
}
- 功能:将数据保存到 Redis 中,并设置过期时间。
- 参数:
key
:Redis 键名,value
:要保存的值,time
:过期时间,单位为毫秒。 - 返回:保存成功返回
true
,否则返回false
。 - 实现:
- 如果
time > 0
,调用redisTemplate.opsForValue().set(key, value, time, TimeUnit.MILLISECONDS)
保存数据并设置过期时间。 - 如果
time <= 0
,直接调用set()
方法保存数据。
- 如果
6. expire 方法
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.MILLISECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
- 功能:设置 Redis 键的过期时间。
- 参数:
key
:Redis 键名,time
:过期时间,单位为毫秒。 - 返回:设置成功返回
true
,否则返回false
。 - 实现:调用
redisTemplate.expire(key, time, TimeUnit.MILLISECONDS)
设置过期时间。
7. getQueueList 方法
public List<V> getQueueList(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
- 功能:获取 Redis 列表(队列)的所有元素。
- 参数:
key
:Redis 键名。 - 返回:Redis 列表的所有元素,返回类型是
List<V>
。 - 实现:调用
redisTemplate.opsForList().range(key, 0, -1)
获取整个列表。
8. lpush 方法
public boolean lpush(String key, V value, Long time) {
try {
redisTemplate.opsForList().leftPush(key, value);
if (time != null && time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
- 功能:将元素插入到 Redis 列表的头部。
- 参数:
key
:Redis 键名,value
:要插入的值,time
:可选的过期时间,单位为秒。 - 返回:插入成功返回
true
,否则返回false
。 - 实现:
- 调用
redisTemplate.opsForList().leftPush(key, value)
将元素添加到列表头部。 - 如果
time > 0
,则调用expire()
方法设置过期时间。
- 调用
9. remove 方法
public long remove(String key, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, 1, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
- 功能:从 Redis 列表中删除指定元素。
- 参数:
key
:Redis 键名,value
:要删除的值。 - 返回:删除成功返回被删除的元素数量,失败返回
0
。 - 实现:调用
redisTemplate.opsForList().remove(key, 1, value)
删除元素。
10. lpushAll 方法
public boolean lpushAll(String key, List<V> values, long time) {
try {
redisTemplate.opsForList().leftPushAll(key, values);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
- 功能:将多个元素插入到 Redis 列表的头部。
- 参数:
key
:Redis 键名,values
:要插入的值列表,time
:可选的过期时间,单位为秒。 - 返回:插入成功返回
true
,否则返回false
。 - 实现:
- 调用
redisTemplate.opsForList().leftPushAll(key, values)
将多个元素插入到列表头部。 - 如果
time > 0
,则调用expire()
方法设置过期时间。
- 调用
11. rpop 方法
public V rpop(String key) {
try {
return redisTemplate.opsForList().rightPop(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
- 功能:从 Redis 列表的尾部弹出一个元素。
- 参数:
key
:Redis 键名。 - 返回:弹出的元素,如果发生异常则返回
null
。 - 实现:调用
redisTemplate.opsForList().rightPop(key)
弹出列表尾部元素。
12. increment 方法
public Long increment(String key) {
Long count = redisTemplate.opsForValue().increment(key, 1);
return count;
}
- 功能:将指定键的值增加 1(如果键不存在,则创建并设置为 1)。
- 参数:
key
:Redis 键名。 - 返回:增加后的值。
- 实现:调用
redisTemplate.opsForValue().increment(key, 1)
增加值。
13. incrementex 方法
public Long incrementex(String key, long milliseconds) {
Long count = redisTemplate.opsForValue().increment(key, 1);
if (count == 1) {
expire(key, milliseconds);
}
return count;
}
- 功能:将指定键的值增加 1,并在首次设置时设置过期时间。
- 参数:
key
:Redis 键名,`milliseconds