SpringBoot中使用redis数据库

166 阅读6分钟

1. Redis的Java客户端

Redis 的 Java 客户端很多,常用的几种:

  • Jedis
  • Lettuce
  • Spring Data Redis

Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。

这里重点学习Spring Data Redis

2. Spring Data Redis使用方式

2.1 介绍

Spring Data Redis 是Spring的一部分,提供了在 Spring 应用中通过简单的配置就可以访问Redis服务,对Redis底层开发包进行了高度封装。在Spring项目中,可以使用Spring Data Redis来简化Redis 操作。

官网:spring.io/projects/sp…

image-20240306172701871

Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

  • ValueOperations:string数据操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:hash类型的数据操作
  • ListOperations:list类型的数据操作

2.2 环境搭建

2.2.1 导入依赖

1)新建项目:

image-20240306211216448

直接在新建项目时可以将Spring Data Redis集成进来。

2)现有项目:

pom.xml文件中添加如下maven坐标

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.2.2 配置Redis数据源

在配置文件中配置自己的Redis服务端地址和密码等:

# Redis配置
spring:
  data:
    redis:
      host: localhost # Redis服务端地址
      port: 6379 # Redis服务端端口(默认:6379)
      password: your_password # 服务端密码(没有可以不写该配置项)
      database: 10 # 该项目选择第几个数据库(默认为0号数据库)

其中:passworddatabase不是非必须的。

password:若忘记可以自行查看redis的配置文件(redis.conf)。

database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。

2.2.3 配置序列化器

当前配置不是必须的,因为Spring Boot框架会自动装配RedisTemplate对象,但是默认的key序列化器会导致我们存到Redis中后的数据和原始数据有差别,会显示出一些乱码,但并没有错,只是用不同的序列化器,为了又更好的兼容性,还是建议配置一下序列化器。

package com.dgxz99.configruation;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
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 RedisConfiguration {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 字符串序列化器
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // JSON序列化器
        // Jackson序列化的映射器配置
        ObjectMapper mapper = new ObjectMapper();
        // 添加Java 8时间支持模块
        mapper.registerModule(new JavaTimeModule());
        // 设定序列化策略:直接基于字段而不依赖于getter和setter
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        // 设定对象类型策略
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        // 配置忽略空字段
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 最后创建JSON序列化器
        Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(mapper, Object.class);

        // 设定序列化器
        // 创建Redis模板对象
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        //设置redis的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // key和hashKey通常使用字符串序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        // value和hashValue通常使用JSON序列化方式
        redisTemplate.setValueSerializer(jsonSerializer);
        redisTemplate.setHashValueSerializer(jsonSerializer);

        return redisTemplate;
    }
}

注意:必须将该配置注入Spring容器中,才能生效。注入方式使用Bean注解。

2.3 操作常见数据类型

这里主要是学习怎么使用,故就在Spring Boot中的test类中做示范,一般来说,通常是在Service层装配redisTemplate,然后进行操作。

2.3.1 字符串

/**
* 操作字符串数据类型
*/
@Test
public void testString(){
    // 主要方法:set get setex
    redisTemplate.opsForValue().set("name", "小明");
	
    // 这里默认是返回一个Object类型对象,需要转换为对应类型,若指定键不存在返回null
    // Object name = redisTemplate.opsForValue().get("name");
    String name = (String) redisTemplate.opsForValue().get("name");
    System.out.println(name);

    // TimeUnit是一个Java自带的类,其中枚举了许多时间单位。
    redisTemplate.opsForValue().set("gender","男",2, TimeUnit.MINUTES);
}

先查看一下Redis数据库里的情况,方便查看,这里直接使用数据库图形工具。

image-20240307105347713

image-20240307105645327

image-20240307105331757

可以看到,namegender的值都被保存到数据库里,控制台也输出了name的值,证明get方法获取成功。并且,gender键的右上角有TTL倒计时,等倒计时结束,该key就自动删除了。

然后再解释关于TimeUnit这个类:

TimeUnit是一个Java自带的类,其中枚举了许多时间单位,如下,在设定上时可以自己选择合适的:

image-20240307110148035

前面提到了关于redisTemplate配置是不必要的,但是建议配置,这里我们看看不配置会是怎么样的。

直接注释掉Bean注解,使配置不生效。

image-20240307110405457

/**
* 测试redisTemplate配置类的效果
*/
@Test
void testRedisTemplate() {
    redisTemplate.opsForValue().set("city", "重庆");
    String city = (String) redisTemplate.opsForValue().get("city");
    System.out.println(city);
}

image-20240307110733349

image-20240307110745958

可以发现(忘记贴图了-_-||,可以自己尝试),Redis数据库中出现了一些乱码的问题,但是Idea控制台还是正常输出,并没有任何影响。数据库中产生乱码的原因就是Redis默认的序列化器和Java的序列化器不一致导致的,故还是建议进行配置。

2.3.2 列表

后面就不在示范案例,大家根据语法自行尝试。

// 左插入元素
redisTemplate.opsForList().leftPush(列表的键, 值);

// 右插入元素
redisTemplate.opsForList().rightPush(列表的键, 值);

// 获取指定列表中指定索引的元素值(从0开始)
redisTemplate.opsForList().index(列表的键, 指定索引);

// 设定列表中指定索引的元素值
redisTemplate.opsForList().set(列表的键, 指定索引1, 值);

// 移除指定列表中为指定值的元素并指定移除数量
redisTemplate.opsForList().remove(列表的键, 移除数量, 被移除值);

// 获取列表中指定索引范围的元素,其中0、1、2代表第一、第二、第三个元素;-1、-2、-3代表倒数第一、第二、第三个元素,以此类推
redisTemplate.opsForList().range(列表的键, 起始索引, 终止索引);

2.3.3 哈希

// 设定哈希表中指定字段的值,若该字段不存在则添加该字段和值,存在则修改其值
redisTemplate.opsForHash().put(哈希表的键, 字段, 值);

// 获取指定哈希表中指定字段的值
redisTemplate.opsForHash().get(哈希表的键, 字段);

// 判断某字段是否存在于指定哈希表中
redisTemplate.opsForHash().hasKey(哈希表的键, 待判断字段);

// 删除指定哈希表中指定字段及其值
redisTemplate.opsForHash().delete(哈希表的键, 待删除字段);

2.3.4 集合

// 加入值到集合
redisTemplate.opsForSet().add(集合的键, 值);

// 从集合中移除指定值
redisTemplate.opsForSet().remove(集合的键, 值);

// 判断值是否存在于指定集合内
redisTemplate.opsForSet().isMember(集合的键, 待判断值);

// 获取一个集合内的全部元素
redisTemplate.opsForSet().members(集合的键);

2.3.5 有序集合

// 向指定有序集合添加一个值,若该值已经存在于该有序集合,但是分数和有序集合中该值对应的分数不同,则会更新该值的分数
redisTemplate.opsForZSet().add(有序集合的键, 值, 值的分数);

// 移除有序集合中的指定值
redisTemplate.opsForZSet().remove(有序集合的键, 待移除值);

// 获取有序集合中指定索引范围的值,并按照其分数升序排列,索引0、1、2代表第一、第二、第三个元素;-1、-2、-3代表倒数第一、第二、第三个元素,以此类推
redisTemplate.opsForZSet().range(有序集合的键, 起始索引, 终止索引);

// 获取有序集合中指定索引范围的值,并按照其分数降序排列
redisTemplate.opsForZSet().reverseRange(有序集合的键, 起始索引, 终止索引);