spring boot 整合redis

前言

  本文只适用于初学redis的同学,旨在能够运行项目即可,想进行深入了解的同学,本文可能不会给你带来任何价值

准备工作

  1.本文中涉及的项目是基于spring boot2.x,并且配置了web模块,在开始之前请准备好你的代码环境。

  2.同时,暂时请忘掉你在之前查阅过的,不能使你的项目正常运行的文章。因为一些先入为主的概念,可能会让你变得疑惑,请完全跟随本文的脚步

你必须要了解的一些关系

  1.springboot整合redis的两种连接方式

    jedis:多线程下,非线程安全,所以使用连接池(不支持异步操作),适用springboot1.x

    lettuce:多线程下,线程安全,基于Netty支持异步操作,适用springboot2.x0

  2. spring boot2.x 默认使用lettuce连接,spring-boot-starter-data-redis集成了lettuce-core,引入spring-boot-starter-data-redis之后就不需要引入lettuce-core了,但是版本的lettuce-core需要commons-pool2。

  3.本文项目使用lettuce方式连接

所需的依赖

     //<!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
//<!-- 高版本redis的lettuce需要commons-pool2 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.6.0</version> </dependency>

在application.properties中添加配置

//application.properties
#我们这里只配置必须的一些配置,先让项目运行起来,在做拓展 #配置redis信息 #redis服务器地址 spring.redis.host
=127.0.0.1 #redis服务器端口 spring.redis.port=6379 spring.redis.password=123456789

在application.properties配置后,并不意味着,spring boot会自动为我们配置redis连接,我们还需要定义一个配置类RedisConf

package com.example.demo;

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;

@Configuration //使用注解注入配置,必须要添加,这样application.properties中的配置才能在redis中生效,添加@Configuration之后,spring 会自动扫描注入
public class RedisConf {
    @Bean //声明一个Bean 这样其他地方可以通过@Autowired获取到生成的 RedisTemplate 对象
    public RedisTemplate rt(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(factory);// 配置连接工厂
      //设置键值默认序列化方式
     RedisSerializer stringSerializer = new StringRedisSerializer(); //RedisTemplate有自己的默认序列化的方式,不过使用默认方式,会在redis客户端查看的时候出现乱码,不便与使用,我们这里用falstjson库
     template.setDefaultSerializer(stringSerializer);

return template; } }

 测试是否成功

package com.example.demo;

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

import java.util.concurrent.TimeUnit;

@RestController
public class Index {


    @Autowired
    RedisTemplate rt; //装配之前定义的@bean

    @RequestMapping("/index")
    public String index() {
        //测试redis 是否配置成功
        rt.opsForValue().set("key001", "测试数据 key值是key001", 500, TimeUnit.MINUTES);
        System.out.println(rt.opsForValue().get("key001"));
        return "执行成功";
    }
}

拓展

  1.redis常用配置

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=20
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=1000

  2.RedisTemplate 常用方法

      前言:

        redis有五种数据类型,下文中的rt为RedisTemplate实例对象。

        redis的key值是唯一的,如果为String设置了key001,那么hash类型数据中就不可以在加入key001的key

      常用方法:

        1. string

          (1)增

    //写入一个键和值 key,value;如果已经存在key那么会覆盖已有的key值
    rt.opsForValue().set(key, "value");

    //写入一个key-value,并且设置它的过期时间
       rt.opsForValue().set(key, value, 1000, TimeUnit.MILLISECONDS);

    //将map中的key-value批量添加为redis的key-value;只要redis中已经存在与map相同的key(一个或者多个),那么map中的key-value都不会写入redis;注入成功返回ture,失败则返回false
       Map valMap = new HashMap();
       rt.opsForValue().multiSetIfAbsent(valMap);

    //将map中的值批量注入redis,和multiSetIfAbsent效果一直,不同的是multiSet,即便redis已经存在map中相同的key,也用map的值会覆盖掉redis中原有的key的值,所以这个方法可以用于key的批量增加,和修改; 无返回值
       rt.opsForValue().multiSet(valMap);

 

          (2)删

     //删除指定的key
        rt.delete(key);

        //批量删除key,其中keys:Collection<K> keys
        rt.delete(keys);

 

          (3)改

     // ps:经测试 无效; 在指定key值后增加字符串
        rt.opsForValue().append(key, "新增字符串");

        //为key设置过期时间(倒计时),到时间后直接删除key,而非把值变为null
        rt.expire(key, 2000, TimeUnit.MILLISECONDS);

        //你也可以直接设置到期的时间 过期直接删除key
        rt.expireAt(key, new Date());

        //如果久的key名存在,则将旧的key名改成新的key名;如果不存在旧的key,那么会抛出异常
        rt.rename(oldKey, newKey);

        //将指定的key,移动到指定的redis数据库中,dbIndex:redis数据库索引
        rt.move(key, dbIndex);

        //将key值转化成byte[],return:byte[],如果不存在key,那么return:null
        rt.dump(key); 

          

          (4)查

     //判断是否存在key,return:boolean,存在key返回true,不存在返回false
        rt.hasKey(key); 

        //批量获取key值,返回一个list<>;
        rt.opsForValue().multiGet(keys);

        //通过正则查找匹配的key值,返回一个set集合类型
        rt.keys(Pattern.compile(key).pattern());

        //获取对应key的值,return:string ,不存在key则null
        rt.opsForValue().get(key);

        //返回对应key所储存的值的类型
        rt.type(key);

        //随机取出一个key
        rt.randomKey();

        //设置key过期时间
        rt.expire(key, 1000, TimeUnit.MILLISECONDS);

        //返回对应key值剩余的过期时间,如果不存在key返回-2;如果没有通过expire设置过期时间,则返回-1,表示永久保存
        rt.getExpire(key);
        rt.getExpire(key, TimeUnit.MILLISECONDS);//可以通过第二个参数,设置放回剩余过期时间的单位

        //查询对应key的大小,单位为byte
        rt.opsForValue().size(key);

 

        2. hash

          (1)增、改

    //在对应key的hash表中注入一个字段为field,值为hash val 001的记录;如果对应key已经存在hash表则在hash表中注入字段;如果hash表中字段已经存在相同,则覆盖对应字段的value
        rt.opsForHash().put(key, field, "hash val 00");

        //在对应key的hash表内,增加一个字段filed,并设置对应字段的filed;仅当对应的filed不存在时才设置
        rt.opsForHash().putIfAbsent(key, field, "hash val 01");

        //批量添加对应key下hash表中的记录
        Map m = new HashMap();
        m.put("filed01", "val3");
        m.put("filed02", "val4");
        rt.opsForHash().putAll(key, m);//如果hash表中已经存在相同的字段,那么对字段的值进行覆盖

          

          (2)删

     //删除对应hash表内的一个或多个字段
        rt.opsForHash().delete(key, field);
        String[] str = {"filed01", "filed02"};
        rt.opsForHash().delete(key, str);

 

          (3)改

      //删除对应hash表内的一个或多个字段
        rt.opsForHash().delete(key, field);
        String[] str = {"filed01", "filed02"};
        rt.opsForHash().delete(key, str);

 

          (4)查

    //查看指定hash表内的指定字段是否存在
        rt.opsForHash().hasKey(key, field);

        //查询对应key的hash表中的field字段的值
        rt.opsForHash().get(key, field);

        //获取对应key的hash表的所有的字段名
        rt.opsForHash().keys(key);

        //获取对应key的hash表中的所有字段和值对
        rt.opsForHash().entries(key);

 

        3. list

          (1)增

     //在key对应的list的开头位置插入一个元素
        rt.opsForList().leftPush(key, "第1次插入的元素");
        rt.opsForList().leftPush(key, "指定值", "第2次插入的元素");//在list从左到右顺序,第一个值是"指定值"的元素前面插入值

        //在key对应的list的开头位置插入一个元素,不同的是,只有key对应的list存在时,才插入
        rt.opsForList().leftPushIfPresent(key, "插入的值");


        //在对应key的list中的开头位置批量增加元素;请注意:插入的元素中,越靠前的元素越先插入,这就意味者在list中越晚插入的元素排序位置越靠前
        rt.opsForList().leftPushAll(key, "批量插入元素1", "批量插入元素2");
        Collection<String> items = new ArrayList<>();
        items.add("items01");
        items.add("items02");
        rt.opsForList().leftPushAll(key, items);//也可以使用集合的方式批量插入

        //在对应key的list中的末尾添加元素,和leftPush使用完全一致
        rt.opsForList().rightPush(key, "在末尾添加元素");

        //在末尾批量添加元素,和leftPushAll使用完全一致,区别是一个是在开头插入,一个实在末尾插入
        rt.opsForList().rightPushAll(key, "末尾添加元素1");

 

          (2)删

     //删除从0开始第一个值值为value的元素
        rt.opsForList().remove(key, 0, value);

        //只保留对应key的list中index到pivot位置中的元素
        rt.opsForList().trim(key, index, pivot);

        //移除key对应的list的第一个元素
        rt.opsForList().leftPop(key);
        rt.opsForList().leftPop(key, 5000, TimeUnit.MILLISECONDS);//设置三个参数之后,如果没有存在可移除的元素,那么会阻塞当前进程,直到纯在可以移除的元素,或者到达设置的超时时间为止

        //移除key对应list的最后一个元素
        rt.opsForList().rightPop(key);
        rt.opsForList().rightPop(key, 1000, TimeUnit.MILLISECONDS);

        //将key1对应的list的最后一个元素移除,并将其插入key2对应的list的最开头的位置
        rt.opsForList().rightPopAndLeftPush(key1, key2);
        rt.opsForList().rightPopAndLeftPush(key1, key2, 1000, TimeUnit.MILLISECONDS);//设置三个参数之后,如果没有存在可移除的元素,那么会阻塞当前进程,直到纯在可以移除的元素,或者到达设置的超时时间为止

 

          (3)改

      //设置指定元素的值
        rt.opsForList().set(key, 0, "添加元素 魔改");

        //键list中指定位置的元素保留,其余的全部删除
        rt.opsForList().trim(key, 0, 5);

 

          (4)查

    //获取对应key的list中指定index的元素
        rt.opsForList().index(key, index);

        //获取对应key的list中指定范围的元素
        rt.opsForList().range(key, 0, -1);

        //获取key对应的list内部元素数量
        rt.opsForList().size(key);

 

        4. set

          (1)增、改

 

     //在key对应的set中增加一个元素或多个元素
        rt.opsForSet().add(key, value, "value2", "value3", "value5", "value6", "value7");

 

 

 

          (2)删

 

     //删除key对应的set中一个或多个value
        rt.opsForSet().remove(key, value, value2);

        //删除set随机的一个元素,并将其返回
        rt.opsForSet().pop(key);

 

 

          (3)查

 

     //获取集合中所有的元素
        rs = rt.opsForSet().members(key);

        //判断集合中是否存在指定的value
        rt.opsForSet().isMember(key, value);

        //判断多个个集合的交集,只返回所有集合中都存在的元素
        rt.opsForSet().intersect(key, key2);
        rt.opsForSet().intersect(key, keys);

        //将key对应的与一个或多个集合中的交集储存到destKey集合中
        rt.opsForSet().intersectAndStore(key, key2, destKey);//将key与key2对应集合中元素的交集凡在放在destKey中
        rt.opsForSet().intersectAndStore(key, keys, destKey);//将key与keys中多个集合中对应的元素的交集放在destKey中

        //获取集合中的差集
        rt.opsForSet().difference(key, key2);//比较两个集合的差集
        rt.opsForSet().difference(key, keys);//比较多个集合的差集

        //随机获取集合中的一个元素
        rt.opsForSet().randomMember(key);

        //随机获取集合中指定个数的元素
        rt.opsForSet().randomMembers(key, count);

        //获取集合内部元素数量
        rt.opsForSet().size(key);

 

        

        5.zSet

          (1)增

            

     //在key对应的zSet集合中增加一个元素,score:int 0;在增加元素的过程中,如果zSet已经存在相同的value的元素,那么旧元素的score将会被覆盖
        rt.opsForZSet().add(key, value, score);

 

          (2)删

     //删除对应的元素;
        rt.opsForZSet().remove(key, value);
        rt.opsForZSet().remove(key, value, value2);//批量删除元素

        //移除指定索引位置的元素
        rt.opsForZSet().removeRange(key, start, end);

        //移除指定score范围内的元素
        rt.opsForZSet().removeRangeByScore(key,min,max);//移除指定score范围内的元素

 

          (3)改

      //改变元素的score值
        rt.opsForZSet().incrementScore(key, value, 99);

        //获取多个集合的并集,并将其存储在另一个集合中
        rt.opsForZSet().unionAndStore(key, keys, key2);//keys:为字符串或者字符串集合,为字符串集合的时候合并多个集合

        //获取多个集合的交集,并将其存储在另一个集合中
        rt.opsForZSet().intersectAndStore(key, keys, key2);//使用方式和unionAndStore完全一致

 

          (4)查

     //返回指定index范围的元素
        int start = 0;
        int end = -1;
        rt.opsForZSet().reverseRangeWithScores(key, start, end);

        //返回元素在集合的排名;排名值为元素从小到大的排列位置,从0号位开始;
        rt.opsForZSet().rank(key, value);

        //返回元素在集合的排名,和rank一样,只不过是由大到小排列
        rt.opsForZSet().reverseRank(key, value);

        //返回指定score范围的元素,
        rt.opsForZSet().reverseRangeByScore(key, 0, 100);//返回score是0-100得元素
        rt.opsForZSet().reverseRangeByScore(key, 0, 100, start, count);//可以添加参数,获取指定score区间内,从start号位开始的count个元素

        //根据score获取集合元素数量
        rt.opsForZSet().count(key, 0, 10);

        //获取zSet中集合的数量
        rt.opsForZSet().size(key);

        //获取集合中对应得score值
        rt.opsForZSet().score(key, value);

 

posted @ 2021-07-29 17:50  眼里有激光  阅读(1038)  评论(0编辑  收藏  举报