1、Redis是什么
高性能内存数据库
常用于:缓存(Cache),Session存储,分布式锁,计数器,消息队列(简单场景)
2、基础操作
Redis支持多种数据结构:字符串 (String )、哈希 (Hash )、列表 (List )、集合 (Set ) 和 有序集合 (Sorted Set) 等。
Spring 提供两个常用操作类:
| 类 | 用途 |
|---|---|
RedisTemplate |
通用操作(推荐) |
StringRedisTemplate |
专门操作字符串 |
2.1 注入 RedisTemplate
java
@Autowired
private RedisTemplate<String, Object> redisTemplate;
2.2 String 操作(常用)
java
//存值
redisTemplate.opsForValue().set("name", "zhangsan");
//取值
String name = (String) redisTemplate.opsForValue().get("name");
//设置过期时间(缓存核心)
redisTemplate.opsForValue().set("code", "123456", 5, TimeUnit.MINUTES);
2.3 Hash 操作(对象结构)
java
//存对象字段
redisTemplate.opsForHash().put("user:1", "name", "Tom");
redisTemplate.opsForHash().put("user:1", "age", "18");
//取字段
Object name = redisTemplate.opsForHash().get("user:1", "name");
2.4 List 操作(队列)
java
//左插入
redisTemplate.opsForList().leftPush("list", "a");
//右插入
redisTemplate.opsForList().rightPush("list", "b");
//取范围
List<Object> list = redisTemplate.opsForList().range("list", 0, -1);
2.5 Set 操作(去重)
java
redisTemplate.opsForSet().add("set", "a", "b", "c");
Set<Object> members = redisTemplate.opsForSet().members("set");
2.6 ZSet 操作(有序集合)
java
redisTemplate.opsForZSet().add("score", "Tom", 100);
redisTemplate.opsForZSet().add("score", "Jerry", 200);
//按分数排序
Set<Object> result = redisTemplate.opsForZSet().range("score", 0, -1);
3、Spring Boot 集成 Redis
3.1 引入 Redis 依赖:pom.xml
xml
<!-- Spring Boot Redis Starter -->
<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>
<!-- 序列化支持(使用Jackson) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
3.2 配置 Redis 连接:application.yml
yml
spring:
#Redis配置
redis:
host: localhost
port: 6379
password: #没有密码留空
database: 0 #默认数据库
timeout: 3000 #连接超时时间(ms)
#Lettuce连接池配置
lettuce:
pool:
max-active: 20 # 最大连接数
max-idle: 5 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: 3000 # 获取连接最大等待时间(ms)
3.3 Redis 配置类:RedisConfig
配置Redis 序列化方式,避免乱码,默认 RedisTemplate 会序列化容易乱码
java
package com.example.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
//factory 是一个用于与 Redis 建立连接的工厂类。
template.setConnectionFactory(redisConnectionFactory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
//将 Java 对象序列化为 JSON 字符串,或者将 JSON 字符串反序列化为 Java 对象的工具类
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
//配置ObjectMapper,Jackson核心类,负责对象与JSON之间的转换
ObjectMapper mapper = new ObjectMapper();
//设置字段可见性
//PropertyAccessor.ALL 表示所有字段(包括私有字段、静态字段等)都会被 Jackson 访问
//JsonAutoDetect.Visibility.ANY 表示所有字段都可以被序列化和反序列化
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//启用默认类型信息
//Jackson 在序列化对象时将类型信息(类的全名)包含到 JSON 中,在反序列化时可以恢复原始的类型
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
//设置序列化的ObjectMapper
jackson2JsonRedisSerializer.setObjectMapper(mapper);
//使用StringRedisSerializer来序列化和反序列化redis的key值
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key和hash的key都采用String序列化
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
//value和hash的value都采用String序列化
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
3.4 Redis 工具类:RedisUtil
封装Redis操作的常见方法,方便调用:
缓存操作:set、get、delete、hasKey,getExpire
java
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.concurrent.TimeUnit;
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
//设置缓存,带过期时间.timeout过期时间,timeunit时间单位
public void set(String key, Object value, long timeout, TimeUnit timeUnit) {
redisTemplate.opsForValue().set(key,value,timeout,timeUnit);
}
//获取缓存
public Object get(String key){
return redisTemplate.opsForValue().get(key);
}
//删除缓存
public boolean delete(String key){
return Boolean.TRUE.equals(redisTemplate.delete(key));
}
//判断key是否存在
public boolean hasKey(String key){
return Boolean.TRUE.equals(redisTemplate.hasKey(key));
}
//获取过期时间
public Long getExpire(String key){
return redisTemplate.getExpire(key);
}
}
3.5 Service 层使用 Redis 缓存信息
java
// DepartmentService接口新增方法
public interface DepartmentService {
List<Department> findAll(); // 查询所有科室(带缓存)
Department findById(Integer id); // 根据ID查询(带缓存)
boolean updateDepartment(Department department); // 更新时清除缓存
}
// DepartmentServiceImpl实现
@Service
public class DepartmentServiceImpl implements DepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
@Autowired
private RedisUtil redisUtil;
//缓存key前缀
//查询所有部门的缓存键
private static final String CACHE_KEY_DEPT_ALL = "dept:all";
//查询单个部门的缓存前缀
private static final String CACHE_KEY_DEPT_PREFIX = "dept:";
@Override
public List<Department> findAll() {
// 1. 从缓存中获取
Object cached = redisUtil.get(CACHE_KEY_DEPT_ALL);
if (cached != null) {
return (List<Department>) cached;
}
// 2. 缓存未命中,查询数据库
List<Department> list = departmentMapper.selectList(null);
// 3. 存入缓存,设置10分钟过期
redisUtil.set(CACHE_KEY_DEPT_ALL, list, 10, TimeUnit.MINUTES);
return list;
}
@Override
public Department findById(Integer id) {
String key = CACHE_KEY_DEPT_PREFIX + id;
Object cached = redisUtil.get(key);
if (cached != null) {
return (Department) cached;
}
Department dept = departmentMapper.selectById(id);
if (dept != null) {
redisUtil.set(key, dept, 30, TimeUnit.MINUTES);
}
return dept;
}
@Override
public boolean updateDepartment(Department department) {
int rows = departmentMapper.updateById(department);
if (rows > 0) {
// 更新科室后清除相关缓存
redisUtil.delete(CACHE_KEY_DEPT_ALL);
redisUtil.delete(CACHE_KEY_DEPT_PREFIX + department.getId());
}
return rows > 0;
}
}
3.6 Controller 层调用 Service
java
@RestController
@RequestMapping("/api/departments")
@Api(tags = "科室管理")
public class DepartmentController {
@Autowired
private DepartmentService departmentService;
@GetMapping
@ApiOperation("获取所有科室(带缓存)")
public Result<List<Department>> listAll() {
List<Department> list = departmentService.findAll();
return Result.success(list);
}
@GetMapping("/{id}")
@ApiOperation("根据ID获取科室")
public Result<Department> getById(@PathVariable Integer id) {
Department dept = departmentService.findById(id);
return Result.success(dept);
}
@PutMapping
@ApiOperation("更新科室信息")
public Result<Void> update(@RequestBody Department department) {
boolean success = departmentService.updateDepartment(department);
return success ? Result.success(null) : Result.error(500, "更新失败");
}
}