Spring 框架下 Redis 数据结构的全面解析

Hello , 大家好 , 这个专栏给大家带来的是 Redis 系列 ! 本篇文章给大家带来的是如何通过 Spring 来操作 Redis 中的常见数据结构 , 以及如何通过代码执行 Redis 中的原生命令 .

在这里插入图片描述

本专栏旨在为初学者提供一个全面的 Redis 学习路径,从基础概念到实际应用,帮助读者快速掌握 Redis 的使用和管理技巧。通过本专栏的学习,能够构建坚实的 Redis 知识基础,并能够在实际学习以及工作中灵活运用 Redis 解决问题 .
专栏地址 : Redis 入门实践

一 . 前置操作

1.1 创建项目

我们先来创建一个 Spring Boot 的项目
image.png
image.png
image.png
image.png
然后更改一下配置文件的格式
image.png
image.png

1.2 设置 Redis 的连接信息

在 application.yml 中粘贴下面的代码

spring:
  redis:
    host: 127.0.0.1
    port: 8888

1.3 设置项目分层结构

image.png
image.png
然后在类上面添加 @RestController 注解
那后续我们测试 Redis 的各种方法 , 就通过 Spring Web 中的接口方法来去触发

1.4 注入 Redis

我们要想使用 Redis , 就需要将 Redis 注入到我们的 TestController 中
image.png

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;
}

二 . string 类型

我们通过访问对应的路由 , 来去触发 Redis 的各种操作
image.png

我们只是简单的介绍一下 set 和 get 命令 , 其他命令虽然说跟 Jedis 有一些差别 , 但是仍然可以通过 IDEA 的选项选择出我们需要的方法 , 再按照它的参数要求去编写对应的方法即可
image.png
我们使用 redisTemplate 的时候 , 发现并没有 set / get 相关方法了
这是因为 RedisTemplate 做了进一步的封装
image.png
我们给每个类型设计了不同的对象 , 所以需要我们调用不同的类型来去使用 , 这就跟我们原生的 Jedis 就有一些差异了
我们就可以通过 redisTemplate.opsForValue() 来去操作 string 类型了
image.png

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("/testString")
    public String testString() {
        // 设置键值对
        redisTemplate.opsForValue().set("k1", "111");
        redisTemplate.opsForValue().set("k2", "222");
        redisTemplate.opsForValue().set("k3", "333");

        // 获取键值对
        String value = redisTemplate.opsForValue().get("k1");
        System.out.println("value = " + value);

        return value;
    }
}

然后我们访问 http://127.0.0.1:8080/testString 就可以在控制台看到我们的信息了
image.png

三 . list 类型

我们刚才插入了一些数据 , 那我们要清空一下数据库 .
image.png
但是这并没有 flushdb 这个方法啊 , 而且看了一圈也没提供 flushdb 这个方法啊 .
那 Spring 就提供给我们一个执行原生命令的方法
image.png
那参数里面的 RedisCallback action 就相当于一个回调函数 , 在这个回调函数中写下我们需要执行的 Redis 命令 , 那这个回调函数就会被 RedisTemplate 内部进行执行
我们再来具体看一下 execute 这个方法
image.png
image.png
image.png
image.png
那 RedisConnection 就代表了 Redis 的连接 (就跟 Jedis 对象类似)
那我们也应该传入一个 Redis 连接 , 我们使用 lambda 的方式
现在 execute 的方法中编写一个 lambda 表达式
image.png
然后在 () 中创建 Redis 连接 , 在 {} 中编写要执行的 Redis 语句
image.png
那目前 execute 这个方法还在报错 , 是因为回调函数需要我们返回一个返回值 , 而我们只是清空一下数据库 , 并不需要返回什么 , 所以直接返回一个 null 即可
image.png
然后我们就可以模拟列表的各个方法了

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("/testList")
    public String testList() {
        // 清空数据库
        // 避免上一组的测试数据影响到下一组的测试结果
        redisTemplate.execute((RedisConnection connection) -> {
            connection.flushDb();
            return null;
        });

        // 向列表中添加数据
        // 头插法
        redisTemplate.opsForList().leftPush("key", "111");
        // 尾插法
        redisTemplate.opsForList().rightPush("key", "222");
        redisTemplate.opsForList().rightPush("key", "333");
        redisTemplate.opsForList().rightPush("key", "444");

        // 获取列表中的元素
        List<String> result = redisTemplate.opsForList().range("key", 0, -1);
        System.out.println("result = " + result);

        // 删除操作
        // 头删法
        String value1 = redisTemplate.opsForList().leftPop("key");
        System.out.println("头删法 : " + value1);
        // 尾删法
        String value2 = redisTemplate.opsForList().rightPop("key");
        System.out.println("尾删法 : " + value2);
        return "OK";
    }
}

image.png

四 . set 类型

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Set;

@RestController
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("/testSet")
    public String testSet() {
        System.out.println("测试 集合 类型");

        // 清空数据库
        // 避免上一组的测试数据影响到下一组的测试结果
        redisTemplate.execute((RedisConnection connection) -> {
            connection.flushDb();
            return null;
        });

        // 向集合中添加元素
        redisTemplate.opsForSet().add("key", "111", "222", "333", "444");

        // 获取集合中的元素
        Set<String> result = redisTemplate.opsForSet().members("key");
        System.out.println("集合当中的元素 : " + result);

        // 判断元素是否在集合中
        Boolean exists = redisTemplate.opsForSet().isMember("key", "111");
        System.out.println("该元素是否存在 : " + exists);

        // 获取集合的元素个数
        Long len = redisTemplate.opsForSet().size("key");
        System.out.println("集合的元素个数为 : " + len);

        // 删除元素
        Long delNum = redisTemplate.opsForSet().remove("key", "111", "222");
        System.out.println("删除的元素个数为 : " + delNum);

        return "OK";
    }
}

image.png

五 . hash 类型

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Set;

@RestController
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("/testHash")
    public String testHash() {
        System.out.println("测试 哈希 类型");

        // 清空数据库
        // 避免上一组的测试数据影响到下一组的测试结果
        redisTemplate.execute((RedisConnection connection) -> {
            connection.flushDb();
            return null;
        });

        // 添加元素
        redisTemplate.opsForHash().put("k1", "f1", "111");
        redisTemplate.opsForHash().put("k1", "f2", "222");
        redisTemplate.opsForHash().put("k1", "f3", "333");
        redisTemplate.opsForHash().put("k1", "f4", "444");

        // 获取元素
        String value = (String) redisTemplate.opsForHash().get("k1", "f1");
        System.out.println("value = " + value);

        // 判断是否存在
        Boolean isExists = redisTemplate.opsForHash().hasKey("k1", "f1");
        System.out.println("该元素是否存在 : " + isExists);

        // 获取哈希个数
        Long size = redisTemplate.opsForHash().size("k1");
        System.out.println("集合的元素个数为 : " + size);

        // 删除元素
        redisTemplate.opsForHash().delete("key", "f1", "f2");
        
        return "OK";
    }
}

image.png
要注意的是 , 我们在调用 get 方法的时候
image.png
所以我们需要进行强转

六 . zset 类型

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Set;

@RestController
public class TestController {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @RequestMapping("/testZSet")
    public String testZSet() {
        System.out.println("测试 zset 类型");

        // 清空数据库
        // 避免上一组的测试数据影响到下一组的测试结果
        redisTemplate.execute((RedisConnection connection) -> {
            connection.flushDb();
            return null;
        });

        // 添加元素
        // 注意: 这里的顺序是先 value 再 score
        redisTemplate.opsForZSet().add("key", "zhangsan", 10.0);
        redisTemplate.opsForZSet().add("key", "lisi", 20.0);
        redisTemplate.opsForZSet().add("key", "wangwu", 30.0);

        // 获取所有元素
        Set<String> result1 = redisTemplate.opsForZSet().range("key", 0, -1);// 只获取所有的 members
        Set<ZSetOperations.TypedTuple<String>> result2 = redisTemplate.opsForZSet().rangeWithScores("key", 0, -1);// 既获取 members, 又获取 scores
        System.out.println("所有的成员 : " + result1);
        System.out.println("成员 + 成绩 : " + result2);

        // 查询某个成员的成绩
        Double score = redisTemplate.opsForZSet().score("key", "zhangsan");
        System.out.println("zhangsan 的成绩为 : " + score);

        // 获取有序集合元素个数
        Long len = redisTemplate.opsForZSet().size("key");
        System.out.println("有序集合的元素个数为 : " + len);

        // 返回指定元素所在成绩排名
        Long rank = redisTemplate.opsForZSet().rank("key", "zhangsan");
        System.out.println("该元素成绩所在排名 " + rank);
        
        // 删除元素
        redisTemplate.opsForZSet().remove("key", "zhangsan");
        
        return "OK";
    }
}

image.png
其中 , 要注意的操作是 rangeWithScores 这个方法
我们注意一下他的返回值
image.png
Tuple 很眼熟 , 我们在 Jedis 中介绍过了 , 他是一个元组 , 更通俗来说就是一组打包好的数据 .
那我们只需要按照源码提示我们的方式 , 替换掉泛型即可
image.png


那通过这些简单的命令 , 我们就简单的了解了怎样通过 Spring 来去操作 Redis .
虽然我们并未针对每个数据结构的命令进行详细介绍 , 但是其他方法我们通过 IDEA 的提示也能编写出对应的方法
我们也可以通过 Spring 官网提供的教程来去进行查阅 : https://spring.io/projects/spring-data-redis/

那如果对你产生帮助的话 , 还请一键三连 , 感谢 ~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加勒比海涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值