从七年开发视角带你吃透 Spring Boot 整合 redis (附全流程实战加工具类)
干了七年开发,经手的项目大大小小几十个,Redis 几乎成了我每个项目里的 “标配”。这玩意儿就像开发工具箱里的瑞士军刀,缓存数据、实现分布式锁、做计数器,样样精通。今天就手把手教你如何用 Spring Boot 把 Redis 整合得明明白白,还附上超详细的工具类代码和注释,让你直接上手能用。
一、环境准备
首先确保你的开发环境里有 JDK(建议 1.8 及以上)、Maven 或 Gradle。创建一个 Spring Boot 项目,这里我用 Maven 来管理依赖。在 pom.xml 文件中添加 Spring Boot 整合 Redis 的依赖:
<dependencies>
<!-- Spring Boot Web 依赖,方便后续测试接口 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
有了这两个依赖,基本的开发环境就搭建好了。
二、配置 Redis 连接
在 application.yml 文件中配置 Redis 的连接信息,就像给你的程序指明要连到哪台 Redis 服务器:
spring:
redis:
host: localhost # Redis 服务器地址,根据实际情况修改
port: 6379 # Redis 服务器端口
password: # 如果 Redis 设置了密码,在这里填写
database: 0 # 使用的 Redis 数据库编号,默认为 0
lettuce:
pool:
max-active: 8 # 连接池最大连接数
max-idle: 8 # 连接池最大空闲连接数
min-idle: 0 # 连接池最小空闲连接数
max-wait: -1ms # 获取连接最大等待时间,-1 表示无限制
这些配置就像给 Redis 连接上了 “导航”,让程序知道怎么找到它。
三、编写 Redis 工具类
接下来就是重头戏 —— 编写 Redis 工具类。这个工具类就像你和 Redis 对话的 “翻译官”,封装了常用的操作方法。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
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 void delete(String key) {
redisTemplate.delete(key);
}
// 判断缓存是否存在
public boolean exists(String key) {
return redisTemplate.hasKey(key);
}
// 设置哈希表字段和值
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);
}
// 删除哈希表字段
public void hdel(String key, Object... hashKeys) {
redisTemplate.opsForHash().delete(key, hashKeys);
}
// 向列表右侧添加元素
public void rpush(String key, Object... values) {
redisTemplate.opsForList().rightPushAll(key, values);
}
// 获取列表指定范围的元素
public List<Object> lrange(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
// 向集合中添加元素
public void sadd(String key, Object... values) {
redisTemplate.opsForSet().add(key, values);
}
// 获取集合所有元素
public Set<Object> smembers(String key) {
return redisTemplate.opsForSet().members(key);
}
// 对键进行自增操作
public Long incr(String key) {
return redisTemplate.opsForValue().increment(key);
}
// 对键进行自减操作
public Long decr(String key) {
return redisTemplate.opsForValue().decrement(key);
}
}
工具类里把字符串、哈希、列表、集合等常用数据结构的操作方法都封装好了,后续使用直接调用就行。
四、实战测试
在 controller 层编写接口来测试我们的 Redis 工具类,比如编写一个简单的缓存测试接口:
import com.example.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RedisTestController {
@Autowired
private RedisUtils redisUtils;
@GetMapping("/setCache")
public String setCache() {
redisUtils.set("testKey", "testValue");
return "缓存设置成功";
}
@GetMapping("/getCache")
public Object getCache() {
return redisUtils.get("testKey");
}
}
启动 Spring Boot 项目,访问 http://localhost:8080/setCache 设置缓存,再访问 http://localhost:8080/getCache 获取缓存,就能看到效果了。
五、工具类的应用场景代码
1. 缓存热点数据场景
比如在一个电商系统中,商品的详情页数据访问量很大,我们可以把商品详情缓存起来,减轻数据库压力。
import com.example.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@Autowired
private RedisUtils redisUtils;
@GetMapping("/product/{productId}")
public Object getProductDetails(@PathVariable String productId) {
// 先从 Redis 中获取缓存数据
Object cachedData = redisUtils.get("product:" + productId);
if (cachedData != null) {
return cachedData;
}
// 如果 Redis 中没有,从数据库查询
Object productDetails = getProductDetailsFromDB(productId);
// 将查询结果存入 Redis 缓存,设置过期时间为 1 小时
redisUtils.set("product:" + productId, productDetails, 1, TimeUnit.HOURS);
return productDetails;
}
private Object getProductDetailsFromDB(String productId) {
// 这里模拟从数据库查询商品详情的逻辑
return "商品详情数据";
}
}
2. 分布式锁场景
在分布式系统中,多个服务实例同时访问共享资源时,需要使用分布式锁避免数据不一致。下面是一个简单的基于 Redis 的分布式锁示例:
import com.example.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DistributedLockController {
@Autowired
private RedisUtils redisUtils;
private static final String LOCK_KEY = "distributed_lock";
private static final long LOCK_EXPIRE_TIME = 10L; // 锁过期时间,单位秒
@GetMapping("/doSomething")
public String doSomething() {
String lockValue = System.currentTimeMillis() + "";
boolean lockAcquired = redisUtils.setIfAbsent(LOCK_KEY, lockValue, LOCK_EXPIRE_TIME, TimeUnit.SECONDS);
if (lockAcquired) {
try {
// 执行业务逻辑
System.out.println("获取到锁,执行业务操作");
return "操作成功";
} finally {
// 释放锁
if (lockValue.equals(redisUtils.get(LOCK_KEY))) {
redisUtils.delete(LOCK_KEY);
}
}
} else {
return "锁被占用,稍后重试";
}
}
}
在 RedisUtils 工具类中补充 setIfAbsent 方法:
public boolean setIfAbsent(String key, Object value, long timeout, TimeUnit unit) {
return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit);
}
3. 计数器场景
在统计网站的访问量、用户的点赞数等场景中,Redis 的原子自增操作非常实用。
import com.example.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CounterController {
@Autowired
private RedisUtils redisUtils;
private static final String PAGE_VIEW_COUNT_KEY = "page_view_count";
@GetMapping("/incrementPageView")
public Long incrementPageView() {
return redisUtils.incr(PAGE_VIEW_COUNT_KEY);
}
@GetMapping("/getPageViewCount")
public Long getPageViewCount() {
return (Long) redisUtils.get(PAGE_VIEW_COUNT_KEY);
}
}
通过这些应用场景代码,相信你能更清楚地知道 Redis 工具类在实际项目中怎么用了。开发这条路,就是在不断实践和踩坑中成长,希望这些经验和代码能帮你少走些弯路!