Redis集成与基础操作

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, "更新失败");
    }
}
相关推荐
用户8307196840822 小时前
Spring Prototype Bean的四种正确使用方式
java·spring boot·后端
untE EADO3 小时前
SpringBoot:几种常用的接口日期格式化方法
java·spring boot·后端
amIZ AUSK3 小时前
Redis——使用 python 操作 redis 之从 hmse 迁移到 hset
数据库·redis·python
青槿吖3 小时前
第一篇:Redis集群从入门到踩坑:3主3从保姆级搭建+核心原理一次性讲透|面试必看
前端·redis·后端·面试·职场和发展·bootstrap·html
番茄去哪了4 小时前
任务调度功能实现
java·开发语言·spring boot
_MyFavorite_4 小时前
JAVA重点基础、进阶知识及易错点总结(15)缓冲流 + 转换流
java·开发语言·spring boot
2601_949814495 小时前
使用Kubernetes部署Spring Boot项目
spring boot·容器·kubernetes
zs宝来了5 小时前
Redis 网络模型:IO 多路复用与 ae 事件循环
redis·epoll·事件循环·io多路复用·网络模型
羊小猪~~5 小时前
Redis学习笔记(数据类型、持久化、事件、管道、发布订阅等)
开发语言·数据库·c++·redis·后端·学习·缓存