springboot操作redis笔记

RedisTemplate&StringRedisTemplate

一.springboot整合redis

  1. string Redis template是Redis template的子类,也就是说Redis template里有的成员方法string redis template中都有,而且string Redis template 中还包括自己的成员方法;两个的操作数据类型不同

  2. string redis template 的传入键值类型是string类型,意味着StringRedisTemplate的key和value都只能是字符串。

  3. redis template传入的泛型object类型,意味着存储的key和value都可以是一个对象。

    1.配置环境

    1.首先配置redis环境,这里选用插件Spring Initializr进入

    image-20220816145659255

2.然后选择组件的时候

image-20220816145916873

3.进入配置好的项目,首先查看maven的架包是否有错,接着引入redis依赖,这里不指定版本号

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

4.配置application.yml文件

spring.redis.host=192.168.253.10    #ip地址
spring.redis.port=7000				#redis端口号
spring.redis.database=0				#指定数据库

使用StringRedisTemplate

package com.shujia.SpringBootRedis.controller;

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

import java.util.*;

@RestController//返回页面用controller,返回数据用@RestController,或者使用@Controller和@ResponseBody效果也是一样的
public class String_RedisTemplateController {
    //springboot操作redis可以使用自己提供的redis依赖对象,父工程中已经从定义好了两个类供我们使用
    //RedisTemplate和StringRedisTemplate


    //通过对象注入的方式,使用该类的对象
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringredisTemplate;

    @RequestMapping("testkey")
    public String test(){
        //获取当前库中所有的键
//        Set<String> keys = stringredisTemplate.keys("*");
//
//        if (keys != null) {
//            for (String key : keys) {
//                System.out.println(key);
//            }
//        }else {
//            System.out.println("数据库为空!!!!");
//        }
        //给键设置过期时间
//        stringredisTemplate.expire("age", Duration.ofSeconds(20));
//        stringredisTemplate.expire("age", Duration.ofDays(7));
//        stringredisTemplate.expire("age", Duration.ofHours(6));
//        stringredisTemplate.expire("age", Duration.ofMinutes(30));
//        stringredisTemplate.expire("age", Duration.ofMillis(54));
//        stringredisTemplate.expire("age", Duration.ofNanos(6));
        //判断key是否存在
//        Boolean name = stringredisTemplate.hasKey("name");
//        System.out.println(name);
        //将键移动到其他库中
//        Boolean name = stringredisTemplate.move("name", 1);
//        System.out.println(name);
        //返回随机key
//        String s = stringredisTemplate.randomKey();
//        System.out.println(s);
        //将key改名
//        stringredisTemplate.rename("sal","newsal");
        //返回key所存储的值的存储
//        DataType newsal = stringredisTemplate.type("newsal");
//        System.out.println(newsal);
        //删除key
//        Boolean sal = stringredisTemplate.delete("sal");
//        System.out.println(sal);
        //删除多个键,通过集合传值
//        ArrayList<String> arrayList = new ArrayList<>();
//        arrayList.add("name");
//        arrayList.add("age");
//        arrayList.add("sal");
//        stringredisTemplate.delete(arrayList);
        return "测试与键相关的操作成功!!!";
    }
    @RequestMapping("stringtest")
    public String teststring(){
//        set					设置一个key/value
//        get					根据key获得对应的value
//        stringredisTemplate.opsForValue().set("name","tgf");
//        String name = stringredisTemplate.opsForValue().get("name");
//        System.out.println(name);
//        mset				一次设置多个keyvalue
//        HashMap<String, String > hm = new HashMap<>();
//        hm.put("age","18");
//        hm.put("sal","18000");
//        hm.put("like","睡觉");
//        hm.put("weight","160");
//        hm.put("hight","191");
//        stringredisTemplate.opsForValue().multiSet(hm);
//        mget				一次获得多个key的value
//        ArrayList<String> arrayList = new ArrayList<>();
//        arrayList.add("name");
//        arrayList.add("sal");
//        arrayList.add("like");
//        arrayList.add("weight");
//        arrayList.add("hight");
//        List<String> strings = stringredisTemplate.opsForValue().multiGet(arrayList);
//        for (String string : strings) {
//            System.out.println(string);
//        }
//        getset				获得原始key的值,同时设置新值
//        String andSet = stringredisTemplate.opsForValue().getAndSet("name", "tangguangfeng");
//        System.out.println(andSet);
//        strlen				获得对应key存储value的长度
//        Long name = stringredisTemplate.opsForValue().size("name");
//        System.out.println(name);
//        append				为对应key的value追加内容
//        stringredisTemplate.opsForValue().append("sal","900");
//        getrange 			索引0开始截取value的内容到末尾-1
//        setex				设置一个key存活的有效期(秒)
//        psetex				设置一个key存活的有效期(毫秒)
//        setnx				存在不做任何操作,不存在添加
//        msetnx原子操作(只要有一个存在不做任何操作)可以同时设置多个key,只有有一个存在都不保存
//        decr				进行数值类型的-1操作
//        decrby				根据提供的数据进行减法操作
//        Incr				进行数值类型的+1操作
//        incrby				根据提供的数据进行加法操作
//        I	ncrbyfloat			根据提供的数据加入浮点数(不是四舍五入)
        return "String测试成功!!";
    }
    @RequestMapping("listest")
    public String listtest(){
//        lpush			将某个值加入到一个key列表头部, 当列表不存在的时候会进行创建
//        stringredisTemplate.opsForList().leftPush("list","1");
//        lpushx			同lpush,但是必须要保证这个key存在  必须在列表进行存在的情况下从左插入
//        stringredisTemplate.opsForList().leftPush("list","1","88");
//        rpush			将某个值加入到一个key列表末尾
//        stringredisTemplate.opsForList().rightPush("list","78");
//        rpushx			同rpush,但是必须要保证这个key存在
//        stringredisTemplate.opsForList().rightPush("list","78","90");
//        lpop			返回和移除列表左边的第一个元素
//        stringredisTemplate.opsForList().leftPop("list");
//        rpop			返回和移除列表右边的第一个元素
//        stringredisTemplate.opsForList().rightPop("list");
//        lrange			获取某一个下标区间内的元素   lrange list 0 -1
//        stringredisTemplate.opsForList().range("list",0,-1);
//        llen			获取列表元素个数
//        stringredisTemplate.opsForList().size("list");
//        lset			设置某一个指定索引的值(索引必须存在)

//        lindex			获取某一个指定索引位置的元素
//        stringredisTemplate.opsForList().index("list",0);
//        lrem			删除重复元素
//        linsert			在某一个元素之前,之后插入新元素
//        ltrim			保留列表中特定区间内的元素
//        stringredisTemplate.opsForList().trim("list",0,-1);
//        查看是否存在这个key
//        Long list = stringredisTemplate.opsForList().leftPushIfPresent("list", "90");
        return "listtest测试成功!!!";
    }
    @RequestMapping("setest")
    public String settest() {
//        sadd			为集合添加元素
        stringredisTemplate.opsForSet().add("set","20","30","40","10","88","56");
//        smembers		显示集合中所有元素 无序
        stringredisTemplate.opsForSet().members("set");
//        scard			返回集合中元素的个数
        stringredisTemplate.opsForSet().size("set");
//        spop			随机返回一个元素 并将元素在集合中删除
        stringredisTemplate.opsForSet().pop("set");
//        smove			从一个集合中向另一个集合移动元素  必须是同一种类型
        stringredisTemplate.opsForSet().move("set","30","newset");
//        srem			从集合中删除一个元素
        stringredisTemplate.opsForSet().remove("set","20");
//        sismember		判断一个集合中是否含有这个元素
        stringredisTemplate.opsForSet().isMember("set","20");
//        srandmember		随机返回元素   后面可以加数字 表示每次返回的个数
        stringredisTemplate.opsForSet().distinctRandomMembers("set",1);
//        sdiff			去掉第一个集合中其它集合含有的相同元素
        stringredisTemplate.opsForSet().difference("set","newset");
//        sinter			求交集
        stringredisTemplate.opsForSet().intersect("set","newwset");
//        sunion			求和集
        stringredisTemplate.opsForSet().union("set","newset");
        return "settest测试成功!!!";
    }
    @RequestMapping("zsetest")
    public String zsettest() {
//        zadd			添加一个有序集合元素  zadd zset 2 xiaohu 3 xiaohu2
        stringredisTemplate.opsForZSet().add("zset","张三",80.0);
        stringredisTemplate.opsForZSet().add("zset","李四",97.0);
        stringredisTemplate.opsForZSet().add("zset","王五",100.0);
        stringredisTemplate.opsForZSet().add("zset","赵六",40.0);
        stringredisTemplate.opsForZSet().add("zset","武器",70.0);
        stringredisTemplate.opsForZSet().add("zset","李八",90.0);
        stringredisTemplate.opsForZSet().add("zset","汤九",89.0);
        stringredisTemplate.opsForZSet().add("zset","卜十",76.0);
         //2.集合插入
        /**
         * 添加多个数据值
         * public Long add(K key, Set<TypedTuple<V>> tuples) {
         * byte[] rawKey = rawKey(key);
         * Set<Tuple> rawValues = rawTupleValues(tuples);
         * return execute(connection -> connection.zAdd(rawKey, rawValues));
         * }
         */
        HashSet<ZSetOperations.TypedTuple<String>> myTypedTuples = new HashSet<>();
        myTypedTuples.add(new MyTypedTuple("aa", 100.0));
        myTypedTuples.add(new MyTypedTuple("bb", 200.0));
        myTypedTuples.add(new MyTypedTuple("cc", 300.0));
        myTypedTuples.add(new MyTypedTuple("dd", 150.0));
        stringredisTemplate.opsForZSet().add("zset",myTypedTuples);
        
//        zcard			返回集合的元素个数
        Long zset = stringredisTemplate.opsForZSet().size("zset");
        Long zset3 = stringredisTemplate.opsForZSet().zCard("zset");
        System.out.println(zset3);
        System.out.println(zset);
//        zrange 			升序

//        zrevrange 		降序返回一个范围内的元素 如果想看看分数 withscores
        stringredisTemplate.opsForZSet().reverseRange("zset",0,-1);
//        zrangebyscore	按照分数查找一个范围内的元素 zrangebyscore zset 0 20 withscores limit 0 2zrank返回排名
        Set<String> zset1 = stringredisTemplate.opsForZSet().rangeByScore("zset", 40, 70);
        for (String s : zset1) {
            System.out.println(s);
        }
//        zrevrank		倒序排名
        stringredisTemplate.opsForZSet().removeRangeByScore("zset",0,100);
//        zscore			显示某一个元素的分数
        String zset2 = stringredisTemplate.opsForZSet().randomMember("zset");
        System.out.println(zset2);
//        zrem			移除某一个元素
        stringredisTemplate.opsForZSet().remove("zset","80");
//        zincrby			给某个特定元素加分
        stringredisTemplate.opsForZSet().incrementScore("zset","80",80l);
        return "zsettest测试成功!!!";
    }
    @RequestMapping("hashtest")
    public String hashtest() {
//        hset			设置一个key/value对
        HashMap<String, String> map = new HashMap<>();
        map.put("name","tgf");
        map.put("age","18");
        map.put("sal","20000");
        map.put("weight","150");
        map.put("height","191");
        map.put("like","sleep");
        map.put("drink","coco");
        stringredisTemplate.opsForHash().putAll("hash",map);
//        hget			获得一个key对应的value
        stringredisTemplate.opsForHash().get("hash","name");
//        hgetall			获得所有的key/value对
        ArrayList<Object> list = new ArrayList<>();
        list.add("name");
        list.add("age");
        list.add("sal");
        list.add("like");
        list.add("height");
        list.add("weight");
        list.add("drink");
        List<Object> hash = stringredisTemplate.opsForHash().multiGet("hash", list);
        for (Object o : hash) {

            System.out.println(o);
        }


//        hdel			删除某一个key/value对
        stringredisTemplate.opsForHash().delete("hash","weight");
//        hexists			判断一个key是否存在
        stringredisTemplate.opsForHash().hasKey("hash","name");
//        hkeys			获得所有的key
        stringredisTemplate.opsForHash().keys("*");
//        hvals			获得所有的value
        stringredisTemplate.opsForHash().values("hash");
//        hmset			设置多个key/value
        stringredisTemplate.opsForHash().putAll("hash1",map);
//        hmget			获得多个key的value
        stringredisTemplate.opsForHash().multiGet("hash1",list);
//        hsetnx			设置一个不存在的key的值
        stringredisTemplate.opsForHash().putIfAbsent("hash1","hahah","89");
//        hincrby			为value进行加法运算(只能针对数值做运行)
        stringredisTemplate.opsForHash().increment("hash1","sal",9000000l);
//        hincrbyfloat	为value加入浮点值

        return "hashtest测试成功!!!";
    }
    @RequestMapping("bittest")
    public  String  bit(){

        return "bittest测试成功!!!!";
    }

    @RequestMapping("test")
    public  String  hello(){
        return "测试模板springboot成功!!!";
    }
}

这里的zset创建了实体类,进行传值

package com.shujia.SpringBootRedis.entity;

import org.springframework.data.redis.core.ZSetOperations;

public class MyTypedTuple<String> implements ZSetOperations.TypedTuple<String> {
    private String value;
    private Double score;


    public MyTypedTuple(String value,Double score){
        this.value = value;
        this.score = score;
    }

    @Override
    public String getValue() {
        return value;
    }

    @Override
    public Double getScore() {
        return score;
    }

    @Override
    public int compareTo(ZSetOperations.TypedTuple<String> o) {
        return 0;
    }
}


使用RedisTemplate

RedisTemplate:Key和Object类型都是Object类型,将key和value当作对象来看待
    既然将key和value当作对象来看待,那么存储的时候,就是存一个对象
    对象存储到数据库中,是一个持久化的过程,对象持久化到数据库中,需要对对象进行序列化
    分析为什么是null?
    首先,name我们使用StringRedisTemplate,而我们现在用RedisTemplate去读,两个类都不一样,可能读不到
    我们回想一下刚刚提到的一点,RedisTemplate会将key和value当作对象来看待,所以需要对key和value做序列化
    那么RedisTemplate就应该把我们传进去的name做序列化,”name“ --->"namexxxx",然后拿着序列化后的值去     redis中找,而redis中并没有namexxxx,所以结果为null
         
    String类刚刚才看的,已经实现了serializable接口,为什么不行呢?
    所以这里,用的应该不是 jdk自己序列化,而是redis中特有的序列化方式
    
    我们使用了redis特有的序列化方式后,结果却依旧没有出来。
    序列化ID,再次插入一次,让两次序列化ID保持一直就可以了。

1.首先如果是存储出一个对象,这个类有没有实现序列化接口?

2.有没有实现redis特有的序列化实现方式?

3.有没有保持插入和取出的序列化id是一致的?

只有这三点都保证的情况下,数据才能出来

package com.shujia.SpringBootRedis.controller;

import com.shujia.SpringBootRedis.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Redis_TemplateController {
    //通过对象注入的方式,使用该类的对象
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @RequestMapping("stringtest1")
    public String stringtest(){
        //先将stringredis进行序列化,设置键序列化
        redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
        Object name1 = redisTemplate.opsForValue().get("name");
        System.out.println(name1);//NULL
        return "stringtest测试成功";

    }
    @RequestMapping("stringtest11")
    //可以通过序列化先传入,再get
    public String stringtest1(){
        //如果传入的是对象,使用JdkSerializationRedisSerializer进行序列化
        redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
//        redisTemplate.opsForValue().set("name1","tgf");
        Object name1 = redisTemplate.opsForValue().get("name1");
        System.out.println(name1);
        return "stringtest测试成功";
    }
    @RequestMapping("stringtest2")

    public String stringtest2(){
//        Student student = new Student("汤光峰","18","hahah");
//        redisTemplate.opsForValue().set("1001",student);
//        Object o = redisTemplate.opsForValue().get("1001");
//        System.out.println(o);
        //字符串使用StringRedisSerializer进行序列化,这样的好处是redis可视化工具里可以看懂
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        redisTemplate.opsForHash().put("1002","tgf","80");

        return "stringtest测试成功";
    }
}
............实现方法与StringRedisTemplate一致

这边如果创建对象进行传值的话,对象要实现serializable接口,并分配序列化ID

package com.shujia.SpringBootRedis.entity;

import java.io.Serializable;

public class Student implements Serializable {

    private static final long serialVersionUID = 6547839622554453185L;
    private String name;
    private String age;
    private String like;

    public Student(String name, String age, String like) {
        this.name = name;
        this.age = age;
        this.like = like;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public String getLike() {
        return like;
    }

    public void setLike(String like) {
        this.like = like;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                ", like='" + like + '\'' +
                '}';
    }
}

二.连接池(是基于jedis的)

添加依赖

<dependency>
     <groupId>redis.clients</groupId>
     <artifactId>jedis</artifactId>
</dependency>

具体代码

 //构建redis资源连接池配置
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        //给定个数
        poolConfig.setMaxTotal(100);

        //根据这个配置来创建redis连接池
        JedisPool jedisPool = new JedisPool(poolConfig, "192.168.253.10", 6888);

        //在连接池中构建redis连接
        Jedis jedis = jedisPool.getResource();

        //拿着这个连接操作redis
        String name1 = jedis.get("name");
        System.out.println(name1);

        //操作完后将连接归还给连接池
        jedis.close();
posted @ 2022-08-23 16:26  996开发  阅读(213)  评论(0)    收藏  举报