[Redis] 渐进式遍历+使用jedis操作Redis+使用Spring操作Redis

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

  • 1. 渐进式遍历
    • 1.1 概述
    • 1.2 常见指令
  • 2. 数据库管理
  • 3. 在Java程序中控制Redis
    • 3.1 为什么可以使用Java支持Redis
    • 3.2 配置Windows环境与服务器的连接
    • 3.3 在Java中操作Redis
      • 3.3.1 准备工作
      • 3.3.2 关于String的操作
      • 3.3.3 关于List的操作
      • 3.3.4 关于Hash的操作
      • 3.3.5 关于set的操作
      • 3.3.6 关于zset的操作
    • 3.4 在Spring中操作Redis
      • 3.4.1 准备工作
      • 3.4.2 使用String
      • 3.4.3 使用List
      • 3.4.4 使用hash
      • 3.4.5 使用set
      • 3.4.6 使用zset

1. 渐进式遍历

1.1 概述

我们在之前学习过一个指令,叫做keys *,这个指令就是把Redis中所有的key采用遍历的方式全部都获取到.但是这个操作比较危险,可能在Redis中存储的key比较多,可能会阻塞Redis,影响其他指令的执行.
这时候我们就需要使用Redis中的渐进式遍历指令,scan指令.通过渐进式遍历,既可以获取到所有的key,同时又不会卡死服务器.这个命令,不是把所有的key一次性都拿到,而是每次执行命令,只获取其中的一小部分,如果key比较多的话,就需要多次执行scan命令,进行多次渐进式遍历.

1.2 常见指令

  • scan
    scan cursor [MATCH pattern] [COUNT count] [TYPE type]
    以渐进式遍历的方式对Redis中所有的键进行遍历.

    • cusor: 表示的是当前从哪个光标开始遍历.其中光标为0的时候,表示的是从头开始遍历所有的key.但是,光标的概念不可以理解为下标,它不是一个连续递增的整数,他只是一个普通的字符串,在每次遍历之后的返回结果中,都会返回下次遍历开始的光标,这个字符串看上去虽然是整数,但是他是一个字符串且和下标不对应,(如果返回的字符串是0,说明遍历已经完成)可能程序员不理解,但是Redis服务器是可以知道这个光标对应的元素的位置的.
    • pattern: 和前面介绍的keys命令是一样的.
    • count: 限制每次返回的元素个数,默认是10,但是需要注意的是,这里的count和MySQL中的limit不一样.count只是客户端给Redis服务器的一个建议,具体返回多少个,需要看具体的情况,比如只有9个key,但是count写的是10.这时候只返回9个key.但是limit是精确的,指定返回多少个就是返回多少个.
    • type: 指定key对应value的类型,其中包含5个通用类型,5个特殊场景使用的类型.
      在这里插入图片描述

    在遍历的过程中,不会在服务器中保存任何的状态信息.比如保存每次遍历之后的光标位置.此处的遍历是可以随时终止的,不会对服务器产生任何的副作用.

    就像我们去吃烧烤,如果有一部分烧烤还没有上来,我们就需要退款,这时候老板就到后厨看了一眼,说已经烤上了,退不了了,再比如我们在遍历Redis服务器中的key的时候,遍历了一半,不想遍历了,但是这时候又取消不了,如果强行退出,这时候服务器就会保存状态,这时候就会对服务造成一定的影响,这时候就相当于服务器保存了客户端的状态.再比如我们去超市买东西,如果我们在结账的时候,发现钱没有带够,后面的东西不想要了,这时候可以不扫后面的商品.这时就像Redis中的渐进式遍历,没有保存之前遍历的状态,可以随时停止.

127.0.0.1:6379> mset k1 val1 k2 val2 k3 val3 k4 val4 k5 val5
OK
127.0.0.1:6379> scan 0 count 3
1) "1"//返回下次开始遍历的光标.
2) 1) "k3"
   2) "k4"
   3) "k5"
127.0.0.1:6379> scan 1 count 3
1) "0"
2) 1) "k1"
   2) "k2"//虽然输入的count是3,但是只遍历了2个.

但是scan也存在一定的缺点.渐进式遍历虽然解决了阻塞的问题,但是如果在遍历的期间键有所变化(增加修改删除),可能会导致重复遍历或者是遗漏.

2. 数据库管理

在我们之前学习MySQL中,有一个非常重要的概念,叫做database.其中一个MySQL服务器中可以有很多个database,一个database中也可以有很多张表.
其实在Redis中,也是有database这样的概念的,只不过不像MySQL那样随意,想创建多少个database就创建多少个.Redis中的database是现成的,用户不可以创建数据库,也不可以删除数据库.
在这里插入图片描述

默认Redis为我们提供了16个数据库.编号为0~15,这16个数据库之间是相互隔离的.默认的情况下使用的是0号数据库.

  • 我们可以通过 select dbIndex(select+数据库编号)的指令来选择数据库.但是在实际使用中我们很少会关注数据库,一般我们使用0号数据库即可.
  • 我们可以使用flushdb清除当前数据库中的所有数据.使用flushall清除Redis服务器中的所有数据.
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> SELECT 0
OK
127.0.0.1:6379> FLUSHDB
OK
127.0.0.1:6379> keys *
(empty array)

3. 在Java程序中控制Redis

3.1 为什么可以使用Java支持Redis

这个问题,就相当于问,我们为什么可以编写出一个自定义的Redis客户端.首先我们需要知道,在网络通行中,我们会使用到很多的"协议",其中这些协议都是固定好的,是在系统内核中或者驱动程序中实现的,程序员只可以选择,不可以修改.其中传输层协议常见的包含两种,一种是TCP协议,一种是UDP协议,**其中Redis在传输层TCP协议的基础上,自定义了应用层协议,这个协议就是RESP协议.**作为第三方的Java,想要开发一个Redis的客户端,也就需要知道Redis的应用层协议,Redis的RESP协议是在官网上开源出来的.

3.2 配置Windows环境与服务器的连接

在Java开发中,我们一般使用idea进行开发,也就是我们不可以在Linux操作系统上直接对Java进行开发,我们是高度依赖Windows环境的.这就需要我们把Windows中的Redis客户端连接到Linux云服务器中的Redis服务器中.这样的操作,就需要通过Linux服务器的外网IP和Redis服务器的端口号来访问到.但是光知道外网IP和端口号还是不行的,因为Redis服务器对应的默认6379端口号是被云服务器的防火墙保护起来的.也就是这个端口不可以在外网中访问到.
但是千万不可以在云服务器中的安全组配置中开放6379端口号,因为Redis的6379端口号安全系数非常低.开放在公网上很容易被黑客入侵.
那怎么办呢,此时就需要我们来配置xshell客户端与Java客户端的ssh端口转发,把云服务器上的Redis端口映射到本地的主机上.

什么是ssh呢?
ssh就是一个应用层网络协议,ssh默认走的是云服务器的22端口.其中ssh协议最重要的功能就是支持端口转发,相当于通过22端口来传递其他端口的数据.
在Windows主机上访问云服务器的6379端口号的时候,ssh就会构造一个数据报,把要访问Redis的请求放到ssh数据报中(访问6379端口号).
在这里插入图片描述
这个数据就会通过22端口发送给服务器,服务器的ssh服务程序,就可以解析出上述数据报,然后把数据报交给6379端口的程序.

比如我们将Windows主机上的8888端口号使用ssh协议映射到服务器上的6379端口号.
在这里插入图片描述
关于这个转发,我们需要在xshell中进行配置,后续就可以把云服务器中的端口当做一个本地的端口使用.

  • 在使用的服务器上右击,选择属性,选择隧道.
    在这里插入图片描述
  • 选择添加,设置侦听端口为8888,目标端口6379.
    在这里插入图片描述
  • 确定之后,重新连接云服务器生效
    在这里插入图片描述
  • 在Windows系统中的cmd操作版面上,输入指令netstat -nao|findstr 8888查看8888端口的连接状态,如果出现一下界面,说明连接正常.
    在这里插入图片描述
  • 配置完成之后,后续我们在Java代码中,就可以直接通过127.0.0.1:8888端口来直接访问到云服务器中的Redis.同时外面的客户端无法访问到云服务器的6379.

3.3 在Java中操作Redis

3.3.1 准备工作

  • 引入jedis依赖
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.3.2</version>
</dependency>
  • 创建Redis连接,并测试连接
public class Main {
    public static void main(String[] args) {
        JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888");//redis连接池
        try (Jedis jedis = jedisPool.getResource()){//获取数据源
            String ping  = jedis.ping();
            System.out.println(ping);
        }
    }
}

返回pong,说明连接成功.
在这里插入图片描述

3.3.2 关于String的操作

  • get,set.
public class Main {
    public static void main(String[] args) {
        JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888");//redis连接池
        try (Jedis jedis = jedisPool.getResource()){//获取数据源
            stringTest(jedis);
        }
    }
    private static void stringTest(Jedis jedis){
        jedis.set("key1","value1");//set一次只可以设置一个键值对
        jedis.set("key2","value2");
        jedis.set("key3","value3");
        String key1 = jedis.get("key1");
        String key2 = jedis.get("key2");
        String key3 = jedis.get("key100");
        System.out.println(key1);
        System.out.println(key2);
        System.out.println(key3);
    }
}

在这里插入图片描述

  • mset,mget
private static void stringTest2(Jedis jedis){
    jedis.flushAll();
    jedis.mset("key1","value1","key2","value2","key3","value3");//key和value交替设置
    List<String> list = jedis.mget("key1","key2","key3");//由于value的值可以重复,所以使用的是list来接收
    System.out.println(list);
}

在这里插入图片描述
在mset的时候,key和value是交替设置的.在mget接收value的时候,由于value的值是可以重复的.所以我们使用List来接收.

  • exists,del
private static void stringTest3(Jedis jedis){
    jedis.flushAll();
    jedis.set("key1","value1");
    Boolean ret = jedis.exists("key1");//返回Boolean,即该key是否存在
    System.out.println(ret);
    Long ret1 = jedis.del("key1");//返回的是Long类型,即删除成功的个数
    System.out.println(ret1);
}

exists返回的是Boolean,即该key是否存在,del返回的是Long类型,即删除成功的个数.

  • keys
private static void stringTest4(Jedis jedis){
    jedis.flushAll();
    jedis.set("key1","value1");
    jedis.set("key2","value2");
    jedis.set("key3","value3");
    jedis.set("key4","value4");
    jedis.set("key100","value100");
    Set<String> keys = jedis.keys("*");//由于key不可以重复,所以我们使用set来接收
    System.out.println(keys);
    Set<String> keys1 = jedis.keys("key?");//?只匹配一个字符
    System.out.println(keys1);
    Set<String> keys2 = jedis.keys("key*");//*可以匹配多个字符
    System.out.println(keys2);
}

在这里插入图片描述

  • expire,ttl
private static void stringTest5(Jedis jedis) throws InterruptedException {
    jedis.flushAll();
    jedis.set("key1","value1");
    jedis.set("key2","value2");
    jedis.set("key3","value3");
    jedis.set("key4","value4");
    jedis.expire("key1",5);
    Long key1 = jedis.ttl("key1");
    System.out.println(key1);
    Thread.sleep(6000);//阻塞6秒
    boolean ret = jedis.exists("key1");
    System.out.println(ret);
}

在这里插入图片描述

  • append
private static void stringTest6(Jedis jedis){
    jedis.flushAll();
    jedis.set("key1","value1");
    jedis.append("key1", "aaa");
    System.out.println(jedis.get("key1"));
}

在这里插入图片描述

  • getrange,setrange
    getrange获取指定字符串区间的字符,setrange设置指定字符串区间的字符.
private static void stringTest7(Jedis jedis){
    jedis.flushAll();
    jedis.set("key1","value1aaaa");
    System.out.println(jedis.getrange("key1", 0, 4));
    jedis.setrange("key1",0,"bbbbb");
    System.out.println(jedis.getrange("key1",0,4));
}

在这里插入图片描述

  • setnx
    如果存在key,则不设置,返回0,不存在,则设置
private static void stringTest8(Jedis jedis){
    jedis.flushAll();
    jedis.set("key1","value1");
    long setnx = jedis.setnx("key1", "value1");
    System.out.println(setnx);
}

在这里插入图片描述

  • setex
    设置键值对,并设置过期时间
private static void stringTest9(Jedis jedis) throws InterruptedException {
    jedis.flushAll();
    jedis.setex("key1",2,"value1");
    Thread.sleep(3000);
    String s = jedis.get("key1");
    System.out.println(s);
}

在这里插入图片描述

  • incr,decr
    给指定的key对应的value+1或-1
private static void stringTest10(Jedis jedis){
    jedis.flushAll();
    jedis.set("key1","1");
    jedis.incr("key1");
    System.out.println(jedis.get("key1"));
    jedis.decr("key1");
    System.out.println(jedis.get("key1"));
}

在这里插入图片描述

  • incrby,decrby
private static void stringTest11(Jedis jedis){
    jedis.flushAll();
    jedis.set("key1","1");
    jedis.incrBy("key1",2);
    System.out.println(jedis.get("key1"));
    jedis.decrBy("key1",2);
    System.out.println(jedis.get("key1"));
}

在这里插入图片描述

3.3.3 关于List的操作

  • lpush,lpop
private static void listTest1(Jedis jedis){
    jedis.flushAll();
    jedis.lpush("list1","v1","v2","v3");
    System.out.println(jedis.lpop("list1"));
    System.out.println(jedis.lpop("list1"));
    System.out.println(jedis.lpop("list1"));
}

在这里插入图片描述

  • rpush,rpop
private static void listTest2(Jedis jedis){
    jedis.flushAll();
    jedis.rpush("key1","v1","v2","v3");
    System.out.println(jedis.rpop("key1"));
    System.out.println(jedis.rpop("key1"));
    System.out.println(jedis.rpop("key1"));
}

在这里插入图片描述

  • lrange
    查看指定下标区间的元素
private static void listTest3(Jedis jedis){
    jedis.flushAll();
    jedis.rpush("key1","v1","v2","v3");
    System.out.println(jedis.lrange("key1",0,1));//左闭右闭
}

在这里插入图片描述

  • blpop
private static void listTest4(Jedis jedis){
    jedis.flushAll();
    jedis.lpush("key1","v1");
    System.out.println(jedis.blpop(0, "key1"));
    System.out.println(jedis.blpop(5, "key1"));
}

在这里插入图片描述
brpop和blpop同理,这里不再赘述.

  • lindex
    获取指定下标的元素
private static void listTest5(Jedis jedis){
    jedis.flushAll();
    jedis.lpush("key1","v1","v2","v3");
    System.out.println(jedis.lindex("key1", 2));
}

在这里插入图片描述

  • linsert
    在指定的元素之前或者之后插入指定元素.
private static void listTest6(Jedis jedis){
    jedis.flushAll();
    jedis.lpush("key1","v1","v2");
    jedis.linsert("key1", ListPosition.BEFORE,"v2","100");
    System.out.println(jedis.lrange("key1",0,-1));
}

在这里插入图片描述

  • llen
private static void listTest7(Jedis jedis){
    jedis.flushAll();
    jedis.rpush("key1","v1","v2","v3");
    System.out.println(jedis.llen("key1"));
}

在这里插入图片描述

3.3.4 关于Hash的操作

  • hset,hget
private static void hashTest1(Jedis jedis){
    jedis.flushAll();
    jedis.hset("key1","field1","value1");
    jedis.hset("key1","field2","value2");
    jedis.hset("key1","field3","value3");
    System.out.println(jedis.hget("key1", "field1"));
    System.out.println(jedis.hget("key1", "field2"));
    System.out.println(jedis.hget("key1", "field3"));
}

在这里插入图片描述

  • hexists,hdel
private static void hashTest2(Jedis jedis){
    jedis.flushAll();
    jedis.hset("key1","field1","value1");
    jedis.hset("key1","field2","value2");
    jedis.hset("key1","field3","value3");
    System.out.println(jedis.hexists("key1", "field1"));
    System.out.println(jedis.hexists("key1", "field100"));
    jedis.hdel("key1","field1");
    System.out.println(jedis.hgetAll("key1"));
}

在这里插入图片描述

  • hkeys,hvals
private static void hashTest3(Jedis jedis){
    jedis.flushAll();
    jedis.hset("key1","field1","value1");
    jedis.hset("key1","field2","value2");
    jedis.hset("key1","field3","value3");
    System.out.println(jedis.hkeys("key1"));//获取所有的key
    System.out.println(jedis.hvals("key1"));//获取所有的val
}

在这里插入图片描述

  • hmget
private static void hashTest4(Jedis jedis){
    jedis.flushAll();
    jedis.hset("key1","field1","value1");
    jedis.hset("key1","field2","value2");
    jedis.hset("key1","field3","value3");
    System.out.println(jedis.hmget("key1","field1","field2"));
}

在这里插入图片描述

  • hlen
private static void hashTest5(Jedis jedis){
    jedis.flushAll();
    jedis.hset("key1","field1","value1");
    jedis.hset("key1","field2","value2");
    jedis.hset("key1","field3","value3");
    System.out.println(jedis.hlen("key1"));
}

在这里插入图片描述

  • hincrby,hincrbyfloat
private static void hashTest6(Jedis jedis){
    jedis.flushAll();
    jedis.hset("key1","field1","2");
    jedis.hincrBy("key1","field1",1);
    System.out.println(jedis.hget("key1","field1"));
    jedis.hincrByFloat("key1","field1",1.5);
    System.out.println(jedis.hget("key1","field1"));
}

在这里插入图片描述

3.3.5 关于set的操作

  • sadd,smember
private static void setTest1(Jedis jedis){
   jedis.flushAll();
   jedis.sadd("key1","m1","m2","m3");
   jedis.sadd("key1","m1");
   System.out.println(jedis.smembers("key1"));
}

在这里插入图片描述

  • srem,sismember
private static void setTest2(Jedis jedis){
    jedis.flushAll();
    jedis.sadd("key1","m1","m2","m3");
    System.out.println(jedis.smembers("key1"));
    jedis.srem("key1","m1");
    System.out.println(jedis.smembers("key1"));
    System.out.println(jedis.sismember("key1", "m1"));
    System.out.println(jedis.sismember("key1", "m2"));
}

在这里插入图片描述

  • scard
private static void setTest3(Jedis jedis){
    jedis.flushAll();
    jedis.sadd("key1","m1","m2","m3");
    System.out.println(jedis.scard("key1"));
}

在这里插入图片描述

  • sinter
private static void setTest4(Jedis jedis){
    jedis.flushAll();
    jedis.sadd("key1","m1","m2","m3");
    jedis.sadd("key2","m2","m3","m4");
    System.out.println(jedis.sinter("key1","key2"));
}

在这里插入图片描述
sunion和sdiff是同样的道理,这里不再赘述.

3.3.6 关于zset的操作

  • zadd,zrange,zrangeWithScores
private static void zsetTest1(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    System.out.println(jedis.zrange("key1",0,-1));
    System.out.println(jedis.zrangeWithScores("key1",0,-1));//返回的是带有分数的二元组
}

在这里插入图片描述

  • zrem,zcard
private static void zsetTest2(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    jedis.zrem("key1","guanyu");
    System.out.println(jedis.zcard("key1"));
    System.out.println(jedis.zrangeWithScores("key1",0,-1));
}

在这里插入图片描述

  • zcount
    返回指定分数区间的所有key
private static void zsetTest3(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    System.out.println(jedis.zcount("key1",90,91));
}

在这里插入图片描述

  • zpopmax,zpopmin
private static void zsetTest4(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    System.out.println(jedis.zpopmax("key1"));
    System.out.println(jedis.zpopmin("key1"));
}

在这里插入图片描述

  • zrank
    按升序的顺序返回指定元素的排名
private static void zsetTest5(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    System.out.println(jedis.zrank("key1","guanyu"));
}

在这里插入图片描述

  • zscore
    获取指定元素的分数.
private static void zsetTest6(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    System.out.println(jedis.zscore("key1","zhaoyun"));
}

在这里插入图片描述

  • zincrby
    给指定的元素加上指定的分数
private static void zsetTest7(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    jedis.zincrby("key1",10,"zhaoyun");
    System.out.println(jedis.zscore("key1","zhaoyun"));
}

在这里插入图片描述

  • zinterstore
private static void zsetTest8(Jedis jedis){
    jedis.flushAll();
    jedis.zadd("key1",90,"zhangfei");
    jedis.zadd("key1",91,"zhaoyun");
    jedis.zadd("key1",92,"guanyu");
    jedis.zadd("key2",90,"zhangfei");
    jedis.zadd("key2",91,"zhaoyun");
    jedis.zadd("key2",93,"zhugeliang");
    jedis.zinterstore("key3","key1","key2");
    System.out.println(jedis.zrangeWithScores("key3",0, -1));
}

在这里插入图片描述
union和diff是同样的道理,这里不再赘述.

3.4 在Spring中操作Redis

3.4.1 准备工作

首先,我们需要创建一个Spring项目,在创建项目的时候,我们需要引入"Spring Data Redis"和"Spring Web"依赖.
在这里插入图片描述
之后我们需要配置Redis的主机与端口号.在yml配置文件中配置一下内容:

spring:
  redis:
    host: 127.0.0.1
    port: 8888

之后我们需要在Controller中注入StringRedisTemplate对象

@RequestMapping("/redis")
@RestController
public class SpringRedis {
    @Autowired
    public StringRedisTemplate redisTemplate;//注入StringRedisTemplate实例
}

后续我们在操作的时候,就像jedis中共使用jedis对象一样,都用的是注入的redisTemplate对象.

3.4.2 使用String

对于Spring中对Redis的操作,我们不再展示全部方法,有些方法是我们一看就知道什么意思的,学习成本较低,所以我们只展示一部分的方法.

@RequestMapping("/test1")
public String stringTest1(){
    redisTemplate.opsForValue().set("key1","value1");
    return redisTemplate.opsForValue().get("key1");
}

在这里插入图片描述
这里我们需要注意的是,Spring中的操作和jedis中的操作有些不一样的地方,我们在Spring中操作的时候,需要提前指定操作value的类型,比如我们上面使用opsForValue()指定的就是value为String类型的数据.
我们还需要注意一下几点:

  • 在我们不知道Spring中的什么方法对应Redis中的方法,我们可以使用lambda表达式的方法来为execute()方法传递我们所要在Redis中所做的事情,在lambda表达式中,使用RedisConnection参数的时候,就可以使用我们熟悉的api来操作Redis了,在lambda表达式中操作Redis的方法与我们前面学习jedis的方法大相径庭.
    比如我们在执行一个Controller方法之前,我们需要清空数据库:
redisTemplate.execute((RedisConnection connection)->{
    connection.flushAll();
    return null;
});
  • 在使用Spring操作数据库的时候,在我们删除其中的键值对的时候,不需要指定操作的数据类型:
@RequestMapping("/test2")
public String stringTest2(){
    redisTemplate.execute((RedisConnection connection)->{
        connection.flushAll();
        return null;
    });
    redisTemplate.opsForValue().set("key1","value1");
    System.out.println(redisTemplate.opsForValue().get("key1"));
    System.out.println(redisTemplate.delete("key1"));
    return "ok";
}

在这里插入图片描述

3.4.3 使用List

这里的opsForList()就相当于Redis原生指令操作中开头的l一样,就是首先声明是要对一个List进行操作.

@RequestMapping("/test3")
public String listTest1(){
    redisTemplate.opsForList().rightPushAll("key1","value1","value2");
    System.out.println(redisTemplate.opsForList().range("key1", 0, -1));
    System.out.println(redisTemplate.opsForList().leftPop("key1"));
    System.out.println(redisTemplate.opsForList().leftPop("key1"));
    System.out.println(redisTemplate.opsForList().leftPop("key1"));
    redisTemplate.delete("key1");
    return "ok";
}

在这里插入图片描述

3.4.4 使用hash

@RequestMapping("/test4")
public String hashTest1(){
    redisTemplate.opsForHash().put("key1","field1","value1");
    redisTemplate.opsForHash().put("key1","field2","value2");
    redisTemplate.opsForHash().put("key1","field3","value3");
    System.out.println(redisTemplate.opsForHash().get("key1","field1"));
    redisTemplate.opsForHash().delete("key1","field1");
    System.out.println(redisTemplate.opsForHash().keys("key1"));
    System.out.println(redisTemplate.opsForHash().values("key1"));
    redisTemplate.delete("key1");
    return "ok";
}

在这里插入图片描述

3.4.5 使用set

@RequestMapping("/test5")
public String setTest(){
    redisTemplate.opsForSet().add("key1","value1","value2","value3");
    System.out.println(redisTemplate.opsForSet().isMember("key1", "value1"));//判断其中是否存在指定元素
    System.out.println(redisTemplate.opsForSet().remove("key1", "value2"));//删除指定元素
    System.out.println(redisTemplate.opsForSet().pop("key1"));//随机弹出一个元素
    System.out.println(redisTemplate.opsForSet().size("key1"));
    redisTemplate.delete("key1");
    return "ok";
}

在这里插入图片描述

3.4.6 使用zset

@RequestMapping("/test6")
public String zsetTest(){
    redisTemplate.delete("key1");
    redisTemplate.opsForZSet().add("key1","zhaoyun",90.0);
    redisTemplate.opsForZSet().add("key1","guanyu",91.0);
    redisTemplate.opsForZSet().add("key1","zhugeliang",92.0);
    System.out.println(redisTemplate.opsForZSet().range("key1", 0, -1));//返回指定区间的成员和分数
    System.out.println(redisTemplate.opsForZSet().count("key1", 90.0, 92.0));//返回指定分数区间的元素个数
    return "ok";
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/881892.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

javase复习day30综合练习

制造假数据 制造数据 练习一 package Demo1;import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; im…

react hooks--React.memo

基本语法 React.memo 高阶组件的使用场景说明&#xff1a; React 组件更新机制&#xff1a;只要父组件状态更新&#xff0c;子组件就会无条件的一起更新。 子组件 props 变化时更新过程&#xff1a;组件代码执行 -> JSX Diff&#xff08;配合虚拟 DOM&#xff09;-> 渲…

数据结构:二叉树OJ题(基础版)

前言 更完两期二叉树的知识之后&#xff0c;来做几道oj题巩固一下基础 一、翻转二叉树 链接&#xff1a;leetcode链接 还是分治思想&#xff0c;将问题分解成左子树和右子树交换&#xff0c;遇到空树停止 采用递归算法做题 TreeNode* invertTree(TreeNode* root) {if(root …

Golang | Leetcode Golang题解之第409题最长回文串

题目&#xff1a; 题解&#xff1a; func longestPalindrome(s string) int {mp : map[byte]int{}for i : 0; i < len(s); i {mp[s[i]]}res : 0for _, v : range mp {if v&1 1 {res v - 1} else {res v}}if res<len(s) {res}return res }

华为HarmonyOS地图服务 3 - 如何开启和展示“我的位置”?

一. 场景介绍 本章节将向您介绍如何开启和展示“我的位置”功能&#xff0c;“我的位置”指的是进入地图后点击“我的位置”显示当前位置点的功能。效果如下&#xff1a; 二. 接口说明 “我的位置”功能主要由MapComponentController的方法实现&#xff0c;更多接口及使用方法…

基于51单片机的手环设计仿真

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;DHT11温湿度采集温湿度&#xff0c;滑动变阻器连接ADC0832数模转换器模拟水位传感器检测水位&#xff0c;通过LCD1602显示信息&#xff0c;然后在程序里设置好是否…

JavaEE: 创造无限连接——网络编程中的套接字

文章目录 Socket套接字TCP和UDP的区别有连接/无连接可靠传输/不可靠传输面向字节流/面向数据报全双工/半双工 UDP/TCP api的使用UDPDatagramSocketDatagramPacketInetSocketAddress练习 TCPServerSocketSocket练习 Socket套接字 Socket是计算机网络中的一种通信机制&#xff0…

代码随想录算法训练营第五十八天 | 拓扑排序精讲-软件构建

目录 软件构建 思路 拓扑排序的背景 拓扑排序的思路 模拟过程 判断有环 写代码 方法一&#xff1a; 拓扑排序 软件构建 题目链接&#xff1a;卡码网&#xff1a;117. 软件构建 文章讲解&#xff1a;代码随想录 某个大型软件项目的构建系统拥有 N 个文件&#xff0c;文…

机器人的动力学——牛顿欧拉,拉格朗日,凯恩

机器人的动力学推导方法有很多&#xff0c;常用得有牛顿&#xff0c;拉格朗日&#xff0c;凯恩等方法&#xff0c;接下来&#xff0c;简单说说他们之间的使用。注&#xff1a;这里不考虑怎么来的&#xff0c;只说怎么应用。 参考1&#xff1a;4-14动力学分析方法-牛顿—欧拉方…

聚焦API安全未来,F5打造无缝集成的解决方案

研究发现&#xff0c;目前超过90%的基于Web的网络攻击都以API端点为目标。随着对API使用需求的增加&#xff0c;这些攻击还会持续增长。现代企业需要一种动态防御策略&#xff0c;在风险升级成代价高昂、令人警惕且往往无法预防的API安全漏洞之前&#xff0c;发现并降低风险。 …

数据库提权【笔记总结】

文章目录 UDF提权以有webshell只有数据库权限条件复现msf工具sql语句提权 MOF提权前言条件复现msf工具php脚本提权 sqlserver提权前言条件xp_cmdshell提权复现 沙盒提权介绍复现 Oracle提权靶场搭建执行任意命令复现 通过注入存储过程提权&#xff08;低权限提升至DBA&#xff…

C++从入门到起飞之——多态 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1. 多态的概念 2. 多态的定义及实现 2.1 多态的构成条件 2.1.1 实现多态还有两个必须重要条件&…

群晖NAS使用Docker本地部署网页版Ubuntu系统并实现无公网IP远程访问

文章目录 前言1. 下载Docker-Webtop镜像2. 运行Docker-Webtop镜像3. 本地访问网页版Linux系统4. 群晖NAS安装Cpolar工具5. 配置异地访问Linux系统6. 异地远程访问Linux系统7. 固定异地访问的公网地址 前言 本文旨在详细介绍如何在群晖NAS部署docker-webtop&#xff0c;并结合c…

通用接口开放平台设计与实现——(31)API服务线程安全问题确认与修复

背景 在本系列的前面一篇博客评论中&#xff0c;有小伙伴指出&#xff0c;API服务存在线程安全问题&#xff1a; https://blog.csdn.net/seawaving/article/details/122905199#comments_34477405 今天来确认下&#xff0c;线程是否安全&#xff1f;如不安全&#xff0c;如何…

高配小主机加装SSD固态硬盘,我选择性能与设计兼备的希捷酷鱼 530

高配小主机加装SSD固态硬盘&#xff0c;我选择性能与设计兼备的希捷酷鱼 530 哈喽小伙伴们好&#xff0c;我是Stark-C~ 我最近入手了零刻的一款新发布的 GTi12 Ultra高性能迷你主机&#xff0c;其出色的配置与强大的功能让我有了将它用作主力机的打算。不过因为它的高配版本搭…

【记录一下VMware上开虚拟端口映射到公网】

材料 win11 和装在vmware上的ubuntu 步骤一在Ubuntu上配置静态地址&#xff0c;配置如下 vim /etc/netplan/01-network-manager-all.yaml(此文件看系统上对应的是哪个文件&#xff0c;建议先备份)network:version: 2renderer: NetworkManagerethernets:ens33:dhcp4: falseadd…

四十一、完成内容添加功能(使用go测试方法)

目录 一、添加model 二、完成相关dao 三、使用测试类进行测试 1、把光标防止要测试的方法上&#xff0c;右击并选择 2、自动会生成一个以dao文件加_test命名的文件 3、在其中完善方法并完成测试 四、完成content_create_handle 一、添加model 按数据库字段以及字段格式完…

Android 如何实现搜索功能:本地搜索?数据模型如何设计?数据如何展示和保存?

目录 效果图为什么需要搜索功能如何设计搜索本地的功能&#xff0c;如何维护呢&#xff1f;总结 一、效果图 二、为什么需要搜索功能 找一个选项&#xff0c;需要花非常多的时间&#xff0c;并且每次都需要指导客户在哪里&#xff0c;现在只要让他们搜索一下就可以。这也是模…

基于SpringBoot+Vue的剧本杀管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

AIGC7: 高通骁龙AIPC开发者沙龙过程记录A

图中是一座高耸的宫殿。 就像AI的出现&#xff0c;慢慢初现端倪&#xff0c;头角峥嵘。 背景 一直以来都比较关注AI的发展&#xff0c;有幸再一次参加异常AI的盛会。 从我的角度看。 高通是一家生产芯片的公司&#xff0c;国内的小米&#xff0c;荣耀&#xff0c;Oppo , Vi…