Skip to content

Java 操作 Redis


基本介绍

Redis 的 Java 客户端很多,常用的几种:Jedis、Lettuce、Spring Data Redis

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

Spring Data Redis

基本介绍

官方网址:https://spring.io/projects/spring-data-redis

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


Maven 依赖坐标

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

RedisTemplate

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

ValueOperations:string 数据操作

SetOperations:set 类型数据操作

ZSetOperations:zset 类型数据操作

HashOperations:hash 类型的数据操作

ListOperations:list 类型的数据操作

RedisTemplate 操作示例

引入依赖

导入 Spring Data Redis 的 maven 坐标

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

配置 Redis 数据源

在 application-dev.yml 中添加如下代码

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

yaml
spring:
  redis:
    host: localhost
    port: 6379
    password: 123456
    database: 10

获取模板对象

java
package com.sky.test;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;

@SpringBootTest
public class SpringDataRedisTest {
    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testRedisTemplate(){
        System.out.println(redisTemplate);
        //string数据操作
        ValueOperations valueOperations = redisTemplate.opsForValue();
        //hash类型的数据操作
        HashOperations hashOperations = redisTemplate.opsForHash();
        //list类型的数据操作
        ListOperations listOperations = redisTemplate.opsForList();
        //set类型数据操作
        SetOperations setOperations = redisTemplate.opsForSet();
        //zset类型数据操作
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
    }
}

操作 String 类型

java
/**
 * 操作字符串类型的数据
 */
@Test
public void testString(){
    // set get setex setnx
    redisTemplate.opsForValue().set("name","小明");
    String city = (String) redisTemplate.opsForValue().get("name");
    System.out.println(city);
    // 若 key 存在,set 方法可以更新 value
    redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
    // 若 key 不存在则会创建并赋值,若存在,不会覆盖 value
    redisTemplate.opsForValue().setIfAbsent("lock","1");
    redisTemplate.opsForValue().setIfAbsent("lock","2");
}

操作 hash 类型

java
/**
 * 操作哈希类型的数据
 */
@Test
public void testHash(){
    // hset hget hdel hkeys hvals
    HashOperations hashOperations = redisTemplate.opsForHash();

    hashOperations.put("100","name","tom");
    hashOperations.put("100","age","20");

    String name = (String) hashOperations.get("100", "name");
    System.out.println(name);

    Set keys = hashOperations.keys("100");
    System.out.println(keys);

    List values = hashOperations.values("100");
    System.out.println(values);

    hashOperations.delete("100","age");
}

操作 List 类型

java
/**
 * 操作列表类型的数据
 */
@Test
public void testList(){
    // lpush lrange rpop llen
    ListOperations listOperations = redisTemplate.opsForList();

    listOperations.leftPushAll("mylist","a","b","c");
    listOperations.leftPush("mylist","d");

    List mylist = listOperations.range("mylist", 0, -1);
    System.out.println(mylist);

    listOperations.rightPop("mylist");

    Long size = listOperations.size("mylist");
    System.out.println(size);
}

操作 set 类型

java
/**
 * 操作集合类型的数据
 */
@Test
public void testSet(){
    //sadd smembers scard sinter sunion srem
    SetOperations setOperations = redisTemplate.opsForSet();

    setOperations.add("set1","a","b","c","d");
    setOperations.add("set2","a","b","x","y");

    Set members = setOperations.members("set1");
    System.out.println(members);

    Long size = setOperations.size("set1");
    System.out.println(size);

    Set intersect = setOperations.intersect("set1", "set2");
    System.out.println(intersect);

    Set union = setOperations.union("set1", "set2");
    System.out.println(union);

    setOperations.remove("set1","a","b");
}

操作 zset 类型

java
/**
 * 操作有序集合类型的数据
 */
@Test
public void testZset(){
    //zadd zrange zincrby zrem
    ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    zSetOperations.add("zset1","a",10);
    zSetOperations.add("zset1","b",12);
    zSetOperations.add("zset1","c",9);

    Set zset1 = zSetOperations.range("zset1", 0, -1);
    System.out.println(zset1);

    zSetOperations.incrementScore("zset1","c",10);

    zSetOperations.remove("zset1","a","b");
}

常用命令操作

常用命令操作无需模板对象,直接使用 RedisTemplate 类的方法

java
/**
 * 通用命令操作
 */
@Test
public void testCommon(){
    //keys exists type del
    Set keys = redisTemplate.keys("*");
    System.out.println(keys);

    Boolean name = redisTemplate.hasKey("name");
    Boolean set1 = redisTemplate.hasKey("set1");

    for (Object key : keys) {
        DataType type = redisTemplate.type(key);
        System.out.println(type.name());
    }

    redisTemplate.delete("mylist");
}

⭐ 自定义 RedisTemplate

应用场景

RedisTemplate 会通过 Springboot 自动装配功能来自动创建和配置,无需手动配置

默认情况下,RedisTemplate 默认使用 JdkSerializationRedisSerializer 的序列化方式,序列化后的数据保存在 Redis 中,此时这些数据是二进制格式的

如果希望更直观的观察数据,可以采用自定义的 RedisTemplate

序列化方式

序列化方式存储数据格式存储内容举例
JdkSerializationRedisSerializer二进制流(字节数组)不可直接阅读,存储为字节流数据
StringRedisSerializerUTF-8 字符串"name""Alice"
Jackson2JsonRedisSerializerJSON 字符串{"name":"Alice","age":30}

注意事项

序列化方式生效的前提是使用 RedisTemplate 来实现缓存操作

后续一般会采用 Spring Cache 框架来操作缓存数据,序列化方式并不会生效

代码示例

java
package com.sky.config;

import lombok.extern.slf4j.Slf4j;
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.StringRedisSerializer;

@Configuration
@Slf4j
public class RedisConfiguration {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
        log.info("开始创建redis模板对象...");
        RedisTemplate redisTemplate = new RedisTemplate();

        // 默认采用 JdkSerializationRedisSerializer,Redis 的数据为二进制形式

        //设置 redis 的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // StringRedisSerializer,Redis 的数据为 UTF-8 字符串
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        // Jackson2JsonRedisSerializer,Redis 的数据为 JSON 字符串
        redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));

        return redisTemplate;
    }
}