本文目录导读:

- 项目依赖配置 (pom.xml)
- 配置文件 (application.yml)
- Redis配置类
- 实体类
- 服务类 - 涵盖各种操作场景
- Controller 测试接口
- Redis工具类封装
- 异常处理建议
- 常见问题及解决方案
下面我给你一个完整的Spring Data Redis实战案例,包含配置、基础操作、序列化配置、以及一些常见的业务场景,这个案例会覆盖你开发中最常用到的功能。
项目依赖配置 (pom.xml)
<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>
<!-- JSON序列化工具 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
配置文件 (application.yml)
spring:
redis:
host: localhost
port: 6379
password: # 如果没有密码可以为空
database: 0
timeout: 5000ms
lettuce:
pool:
max-active: 8 # 最大连接数
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: -1ms # 最大等待时间,-1表示不限制
Redis配置类
package com.example.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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用StringRedisSerializer来序列化和反序列化redis的key
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 使用GenericJackson2JsonRedisSerializer来序列化和反序列化redis的value
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
实体类
package com.example.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String description;
private BigDecimal price;
private Integer stock;
private LocalDateTime createTime;
}
服务类 - 涵盖各种操作场景
package com.example.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import com.example.entity.Product;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private ObjectMapper objectMapper;
// ==================== 1. String 操作 ====================
/**
* 设置字符串值
*/
public void setString(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* 设置带过期时间的字符串值
*/
public void setStringWithExpire(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
/**
* 获取字符串值
*/
public Object getString(String key) {
return redisTemplate.opsForValue().get(key);
}
/**
* 设置过期时间(秒)
*/
public void expire(String key, long seconds) {
redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
}
// ==================== 2. Hash 操作 ====================
/**
* 设置Hash值
*/
public void setHash(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
/**
* 获取Hash值
*/
public Object getHash(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
/**
* 批量设置Hash
*/
public void setHashAll(String key, Map<String, Object> map) {
redisTemplate.opsForHash().putAll(key, map);
}
/**
* 获取整个Hash
*/
public Map<Object, Object> getHashAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
// ==================== 3. List 操作 ====================
/**
* 向列表头部添加元素
*/
public void pushToList(String key, Object value) {
redisTemplate.opsForList().leftPush(key, value);
}
/**
* 向列表尾部添加元素
*/
public void addToList(String key, Object value) {
redisTemplate.opsForList().rightPush(key, value);
}
/**
* 批量添加元素到列表尾部
*/
public void addAllToList(String key, List<Object> values) {
redisTemplate.opsForList().rightPushAll(key, values);
}
/**
* 获取列表元素(range查询)
*/
public List<Object> getList(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
/**
* 从列表中弹出头部元素
*/
public Object popFromList(String key) {
return redisTemplate.opsForList().leftPop(key);
}
// ==================== 4. Set 操作 ====================
/**
* 添加元素到Set
*/
public void addToSet(String key, Object... values) {
redisTemplate.opsForSet().add(key, values);
}
/**
* 获取Set所有元素
*/
public Set<Object> getSetMembers(String key) {
return redisTemplate.opsForSet().members(key);
}
/**
* 移除Set中的元素
*/
public void removeFromSet(String key, Object... values) {
redisTemplate.opsForSet().remove(key, values);
}
// ==================== 5. ZSet 操作 ====================
/**
* 添加元素到ZSet
*/
public void addToZSet(String key, Object value, double score) {
redisTemplate.opsForZSet().add(key, value, score);
}
/**
* 获取ZSet中的元素(按分数排序)
*/
public Set<Object> getZSetWithScore(String key, double min, double max) {
return redisTemplate.opsForZSet().rangeByScore(key, min, max);
}
/**
* 获取ZSet排名(正序,从小到大)
*/
public Long getZSetRank(String key, Object value) {
return redisTemplate.opsForZSet().rank(key, value);
}
// ==================== 6. 通用操作 ====================
/**
* 删除key
*/
public Boolean delete(String key) {
return redisTemplate.delete(key);
}
/**
* 批量删除
*/
public Long delete(List<String> keys) {
return redisTemplate.delete(keys);
}
/**
* 判断key是否存在
*/
public Boolean hasKey(String key) {
return redisTemplate.hasKey(key);
}
/**
* 获取key的剩余过期时间
*/
public Long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
// ==================== 7. 业务场景:缓存商品信息 ====================
/**
* 缓存商品(存储整个对象)
*/
public void cacheProduct(Product product) {
String key = "product:" + product.getId();
// 设置缓存,过期时间为2小时
redisTemplate.opsForValue().set(key, product, 2, TimeUnit.HOURS);
}
/**
* 获取缓存的商品
*/
public Product getCachedProduct(Long productId) {
String key = "product:" + productId;
Object value = redisTemplate.opsForValue().get(key);
if (value instanceof Product) {
return (Product) value;
}
return null;
}
/**
* 缓存商品并设置条件(如果key不存在才设置)
*/
public Boolean cacheIfAbsent(String key, Product product) {
return redisTemplate.opsForValue().setIfAbsent(key, product, 1, TimeUnit.HOURS);
}
// ==================== 8. 分布式锁示例 ====================
/**
* 尝试获取分布式锁
*/
public Boolean tryLock(String lockKey, String requestId, long expireSeconds) {
// 使用setIfAbsent实现分布式锁
Boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId);
if (Boolean.TRUE.equals(result)) {
// 设置过期时间
redisTemplate.expire(lockKey, expireSeconds, TimeUnit.SECONDS);
}
return result;
}
/**
* 释放分布式锁
*/
public void releaseLock(String lockKey, String requestId) {
// 为了防止误删,可以添加Lua脚本进行判断
// 简单实现:直接删除(生产环境建议使用Lua脚本)
String currentValue = (String) redisTemplate.opsForValue().get(lockKey);
if (requestId.equals(currentValue)) {
redisTemplate.delete(lockKey);
}
}
}
Controller 测试接口
package com.example.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.entity.Product;
import com.example.service.RedisService;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private RedisService redisService;
/**
* 测试字符串操作
*/
@PostMapping("/string")
public String testString() {
// 基础字符串
redisService.setString("test:hello", "Hello Redis");
Object value = redisService.getString("test:hello");
// 带过期时间
redisService.setStringWithExpire("test:expire", "This will expire in 5 seconds", 5, java.util.concurrent.TimeUnit.SECONDS);
return "String测试结果: " + value;
}
/**
* 测试对象缓存
*/
@PostMapping("/product")
public String testProduct() {
// 创建商品
Product product = new Product();
product.setId(1L);
product.setName("iPhone 15");
product.setPrice(new BigDecimal("6999.00"));
product.setStock(100);
product.setCreateTime(LocalDateTime.now());
// 缓存商品
redisService.cacheProduct(product);
// 获取商品
Product cachedProduct = redisService.getCachedProduct(1L);
if (cachedProduct != null) {
return "缓存商品成功: " + cachedProduct.getName() + ", 价格: " + cachedProduct.getPrice();
}
return "缓存商品失败";
}
/**
* 测试Hash操作 - 模拟用户信息
*/
@PostMapping("/hash")
public String testHash() {
// 模拟用户信息
Map<String, Object> userInfo = new HashMap<>();
userInfo.put("name", "张三");
userInfo.put("age", 25);
userInfo.put("email", "zhangsan@example.com");
// 存储为用户hash
redisService.setHashAll("user:1001", userInfo);
// 修改某个字段
redisService.setHash("user:1001", "age", 26);
// 获取整个hash
Map<Object, Object> result = redisService.getHashAll("user:1001");
return "Hash用户信息: " + result;
}
/**
* 测试列表操作
*/
@PostMapping("/list")
public String testList() {
// 创建一个任务队列
for (int i = 1; i <= 5; i++) {
redisService.addToList("task:queue", "Task-" + i);
}
// 获取列表长度
Long listSize = redisService.getList("task:queue", 0, -1).size();
// 弹出头部元素
Object firstTask = redisService.popFromList("task:queue");
// 查看剩余任务
List<Object> remainingTasks = redisService.getList("task:queue", 0, -1);
return "任务队列 - 初始大小: " + listSize + ", 弹出: " + firstTask + ", 剩余: " + remainingTasks;
}
/**
* 测试删除
*/
@DeleteMapping("/{key}")
public String deleteKey(@PathVariable String key) {
Boolean deleted = redisService.delete(key);
return deleted ? "删除成功: " + key : "删除失败或key不存在: " + key;
}
}
Redis工具类封装
package com.example.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Redis操作工具类
*/
@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) {
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
public Boolean setIfAbsent(String key, Object value) {
return redisTemplate.opsForValue().setIfAbsent(key, value);
}
// ==================== Hash操作 ====================
public void hSet(String key, String hashKey, Object value) {
redisTemplate.opsForHash().put(key, hashKey, value);
}
public Object hGet(String key, String hashKey) {
return redisTemplate.opsForHash().get(key, hashKey);
}
public Map<Object, Object> hGetAll(String key) {
return redisTemplate.opsForHash().entries(key);
}
// ==================== List操作 ====================
public void lPush(String key, Object value) {
redisTemplate.opsForList().leftPush(key, value);
}
public void rPush(String key, Object value) {
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 boolean delete(String key) {
return Boolean.TRUE.equals(redisTemplate.delete(key));
}
public long delete(String... keys) {
Long count = redisTemplate.delete(Arrays.asList(keys));
return count != null ? count : 0;
}
public boolean hasKey(String key) {
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}
public boolean expire(String key, long timeout) {
return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, TimeUnit.SECONDS));
}
}
异常处理建议
package com.example.exception;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(RedisConnectionFailureException.class)
public String handleRedisConnectionFailure(RedisConnectionFailureException e) {
return "Redis连接失败,请检查Redis服务是否启动: " + e.getMessage();
}
@ExceptionHandler(SerializationException.class)
public String handleSerializationException(SerializationException e) {
return "Redis序列化异常: " + e.getMessage();
}
}
常见问题及解决方案
-
中文乱码问题:确保value序列化使用GenericJackson2JsonRedisSerializer或Jackson2JsonRedisSerializer。
-
对象序列化问题:实体类要实现Serializable接口。
-
Redis连接池耗尽:合理配置连接池参数,设置max-wait时间。
-
key设计规范:推荐使用"业务:模块:id"格式,如"product:info:1001"。
-
缓存穿透问题:使用setIfAbsent或者布隆过滤器。
这个案例覆盖了Spring Data Redis的大部分常用操作,你可以根据需要灵活使用,记得根据实际业务需求调整配置和操作方法!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播