Spring Boot Redis 整合使用样例
Spring Boot 提供了与 Redis 无缝集成的支持,可以通过简单的配置实现缓存管理、数据存储等功能。以下是完整的 Spring Boot Redis 整合教程和使用样例:
一、基础配置
1. 添加依赖
在 pom.xml 文件中添加 Redis 相关依赖:
<dependencies>
<!-- Spring Boot Redis 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 可选:连接池支持 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- Spring Boot Web 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
2. 配置文件
在 application.yml 中配置 Redis 连接信息:
spring:
redis:
host: localhost # Redis 服务器地址
port: 6379 # Redis 端口
database: 0 # Redis 数据库索引
password: # Redis 密码(如果有)
timeout: 10000 # 连接超时时间(毫秒)
lettuce:
pool:
max-active: 8 # 最大连接数
max-wait: -1 # 最大阻塞等待时间(-1表示无限制)
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
二、自定义 Redis 配置类
创建 Redis 配置类,自定义序列化方式和缓存管理器:
package com.example.redis.config;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching // 开启缓存支持
public class RedisConfig {
/**
* 自定义 RedisTemplate,设置序列化器
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置键的序列化器
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
// 设置值的序列化器
GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
template.afterPropertiesSet();
return template;
}
/**
* 自定义缓存管理器
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)) // 默认缓存过期时间1小时
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.disableCachingNullValues(); // 禁用缓存空值
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
/**
* 自定义键生成器
*/
@Bean
public KeyGenerator keyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(":");
sb.append(method.getName());
if (params != null && params.length > 0) {
sb.append(":");
for (int i = 0; i < params.length; i++) {
sb.append(params[i]);
if (i < params.length - 1) {
sb.append(",");
}
}
}
return sb.toString();
};
}
}
三、Redis 操作工具类
创建一个 Redis 操作工具类,封装常用操作:
package com.example.redis.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// ============================== 字符串操作 ==============================
/**
* 设置缓存
*/
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 设置缓存,带过期时间
*/
public void set(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
/**
* 获取缓存
*/
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
/**
* 删除缓存
*/
public Boolean delete(String key) {
return redisTemplate.delete(key);
}
/**
* 批量删除
*/
public Long delete(Collection<String> keys) {
return redisTemplate.delete(keys);
}
/**
* 设置过期时间
*/
public Boolean expire(String key, long timeout, TimeUnit unit) {
return redisTemplate.expire(key, timeout, unit);
}
// ============================== Hash操作 ==============================
/**
* 存储Hash值
*/
public void hset(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
/**
* 获取Hash值
*/
public Object hget(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
/**
* 获取Hash所有字段
*/
public Map<Object, Object> hgetAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* 删除Hash字段
*/
public Long hdel(String key, Object... hashKeys) {
return redisTemplate.opsForHash().delete(key, hashKeys);
}
// ============================== List操作 ==============================
/**
* 左侧插入List
*/
public Long lpush(String key, Object... values) {
return redisTemplate.opsForList().leftPushAll(key, values);
}
/**
* 右侧插入List
*/
public Long rpush(String key, Object... values) {
return redisTemplate.opsForList().rightPushAll(key, values);
}
/**
* 获取List范围
*/
public List<Object> lrange(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
// ============================== Set操作 ==============================
/**
* 添加元素到Set
*/
public Long sadd(String key, Object... values) {
return redisTemplate.opsForSet().add(key, values);
}
/**
* 获取Set所有元素
*/
public Set<Object> smembers(String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 判断元素是否在Set中
*/
public Boolean sismember(String key, Object value) {
return redisTemplate.opsForSet().isMember(key, value);
}
// ============================== ZSet操作 ==============================
/**
* 添加元素到有序集合
*/
public Boolean zadd(String key, Object value, double score) {
return redisTemplate.opsForZSet().add(key, value, score);
}
/**
* 获取有序集合范围
*/
public Set<Object> zrange(String key, long start, long end) {
return redisTemplate.opsForZSet().range(key, start, end);
}
}
四、缓存注解使用样例
1. 实体类
package com.example.redis.entity;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String email;
private Date createTime;
// 构造函数、getter和setter方法
// ...
}
2. Service 层使用缓存注解
package com.example.redis.service;
import com.example.redis.entity.User;
import com.example.redis.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
@CacheConfig(cacheNames = "userCache") // 类级别缓存配置
public class UserService {
@Autowired
private UserMapper userMapper;
/**
* 查询用户,使用缓存
*/
@Cacheable(key = "#id") // 缓存键为id
public User getUserById(Long id) {
// 缓存未命中时执行此方法
System.out.println("从数据库查询用户: " + id);
return userMapper.selectById(id);
}
/**
* 条件缓存
*/
@Cacheable(key = "#username", condition = "#username.length() > 3")
public User getUserByUsername(String username) {
return userMapper.selectByUsername(username);
}
/**
* 更新用户,更新缓存
*/
@CachePut(key = "#user.id")
public User updateUser(User user) {
userMapper.updateById(user);
return user;
}
/**
* 删除用户,清除缓存
*/
@CacheEvict(key = "#id")
public void deleteUser(Long id) {
userMapper.deleteById(id);
}
/**
* 清除所有缓存
*/
@CacheEvict(allEntries = true)
public void clearCache() {
// 此方法仅用于清除缓存
System.out.println("清除所有用户缓存");
}
/**
* 组合缓存操作
*/
@Caching(
cacheable = { @Cacheable(key = "#user.id") },
evict = { @CacheEvict(key = "#user.username") }
)
public User complexCacheOperation(User user) {
// 复杂的缓存操作
return user;
}
}
五、RedisTemplate 直接使用样例
1. Controller 层示例
package com.example.redis.controller;
import com.example.redis.entity.User;
import com.example.redis.service.UserService;
import com.example.redis.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private RedisUtils redisUtils;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
// 使用RedisTemplate操作
redisTemplate.opsForValue().set("user:" + user.getId(), user, 1, TimeUnit.HOURS);
return user;
}
@PutMapping
public User updateUser(@RequestBody User user) {
return userService.updateUser(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
// 使用工具类的示例
@GetMapping("/cache/test")
public String testCache() {
// 字符串操作
redisUtils.set("test:key", "test value", 10, TimeUnit.MINUTES);
// Hash操作
redisUtils.hset("user:1001", "name", "张三");
redisUtils.hset("user:1001", "age", 28);
// List操作
redisUtils.lpush("news:list", "新闻1", "新闻2", "新闻3");
// Set操作
redisUtils.sadd("tags:set", "技术", "Java", "Spring");
// ZSet操作
redisUtils.zadd("score:rank", "user1", 95);
redisUtils.zadd("score:rank", "user2", 88);
return "Redis操作测试成功";
}
}
六、高级应用场景
1. 分布式锁实现
package com.example.redis.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class DistributedLockService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 获取分布式锁
*/
public boolean acquireLock(String lockKey, String requestId, long expireTime) {
return redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, expireTime, TimeUnit.MILLISECONDS);
}
/**
* 释放分布式锁
*/
public boolean releaseLock(String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
return redisTemplate.execute((RedisCallback<Boolean>) connection -> {
Object result = connection.eval(
script.getBytes(),
ReturnType.INTEGER,
1,
lockKey.getBytes(),
requestId.getBytes()
);
return Integer.valueOf(1).equals(result);
});
}
}
2. 缓存预热
package com.example.redis.service;
import com.example.redis.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class CacheWarmUp implements ApplicationRunner {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private UserService userService;
@Override
public void run(ApplicationArguments args) throws Exception {
// 应用启动时预热热点数据
List<User> hotUsers = userService.getHotUsers();
for (User user : hotUsers) {
redisTemplate.opsForValue().set("user:" + user.getId(), user, 1, TimeUnit.HOURS);
}
System.out.println("缓存预热完成,加载了 " + hotUsers.size() + " 个热点用户");
}
}
七、总结
Spring Boot 整合 Redis 主要有以下几种使用方式:
- 缓存注解方式:使用
@Cacheable、@CachePut、@CacheEvict等注解,简单易用 - RedisTemplate 直接操作:灵活控制 Redis 的各种数据结构操作
- 工具类封装:将常用操作封装成工具类,提高代码复用性
在实际项目中,建议根据具体需求选择合适的方式。对于简单的缓存场景,使用注解方式最为便捷;对于复杂的 Redis 操作,则建议使用 RedisTemplate 或封装工具类。
通过合理使用 Redis,可以显著提高应用的性能,减轻数据库压力,特别是在高并发场景下效果明显。