SpringBoot整合Redis

1.RedisTemplate与StringRedisTemplate的区别

在Redis里面,为了确保数据的安全性以及放便快速存储,任何类型的数据,在Redis内部都是采用二进制的方式存储的,这就导致,当我们存入一个字符串时,可能最终取出的结果会乱掉:

我们在存取的时候,这样的效果显然是不想看到的,如何解决?

SpringBoot给我们提供了两种方式:

  • 可以看到StringRedisTemplate继承RedisTemplate

其实他们的区别在于使用的序列化方式不一样,StringRedisTemplate使用的是序列化为String的序列化方式,RedisTemplate使用的是JDK的序列化方式,使用起来不太友好

  • StringRedisTemplate:序列化为String的方式
  • RedisTemplate:序列化方式是JDK的序列化方式

2.Redis命令与StringRedisTemplate方法对应

方法

返回值

对应操作

opsForValue()

ValueOperations<String,String>

操作String

opsForHash()

HashOperations<String, Object, Object>

操作hash

opsForSet()

SetOperations<String, String>

操作set

opsForList()

ListOperations<String, String>

操作list

opsForZSet()

ZSetOperations<String, String>

操作有序set

除此之外,还有一些与Key相关的操作,可直接通过RedisTemplate对象去调用。

3.Key相关的操作

Redis命令

StringRedisTemplate/RedisTemplate

说明

KEYS* KEYS 星key星 KEYS 星key KEYS key星

redisTemplate.keys(key);

获取所有key,模糊查询key(支持通配符*)

EXPIRE key 10

redisTemplate.expire(key,time,TimeUnit.SECONDS);

指定key缓存失效时间

EXPIREAT key 1293840000

redisTemplate.expireAt(key, date);

指定key缓存到期时间

TTL key

redisTemplate.getExpire(key, TimeUnit.SECONDS);

根据key获取过期时间

EXISTS key

redisTemplate.hasKey(key);

判断key是否存在

EXISTS key1 key2 key3

redisTemplate.countExistingKeys(Arrays.asList(key));

检查key存在的数量

DEL key

redisTemplate.delete(key);

删除指定key缓存

DEL key1 key2 key3

redisTemplate.delete(Arrays.asList(keys));

批量删除key

4.String相关的操作

redisTemplate.opsForValue(); // 操作字符串

Redis命令

StringRedisTemplate/RedisTemplate

说明

SET key value

set(key,value)

设置普通缓存

SET key value time

set(key,value,time)

设置缓存过期时间

GET key

get(key)

获取普通缓存

INCE key

increment(key, delta)

递增,可设置增量

DECR key

increment(key, -delta)

递减

SETNX key value

setIfAbsent(key,value)

将 key 的值设为 value ,当且仅当 key 不存在

SETEX key value

setIfPresent(key,value)

判断当前的键的值是否为v,是的话不作操作,不是的话进行替换。如果没有这个键也不会做任何操作

GETSET key value

getAndSet(key, value)

key存在设置新值,并返回旧值

5.Hash相关的操作

redisTemplate.opsForHash(); //操作hash类型

更多操作Redis命令

StringRedisTemplate/RedisTemplate

说明

HMSET key key1 value1 key2 value2

putAll(key, map)

设置缓存

HSET key item value

put(key, item, value)

向一张hash表中放入数据,如果不存在将创建

HGET key item

get(key, item)

获取缓存,字段值

HMGET key

entries(key)

获取hashKey对应的所有键值

HVALS

values(key)

获取hashKey对应的所有键值

HEXISTS key item

hasKey(key, item)

判断hash表中是否有该项的值

HINCRBY key item by

increment(key, item, by)

hash递增 如果不存在,就会创建一个 并把新增后的

HLEN

lengthOfValue(key,hashkey)

获取指定hash键指定键值的长度

6.List相关的操作

redisTemplate.opsForList(); //操作List类型

操作Redis命令

StringRedisTemplate/RedisTemplate

说明

RPUSH key value

rightPush(key, value)

将list放入缓存,从右边添加

LPUSH key value

leftPush(key, value)

将list放入缓存,从左边添加

LRANGE key 0 -1

range(key, start, end)

获取list缓存指定范围的内容

LLEN key

size(key)

获取list缓存的长度

LINDEX key index

index(key, index)

通过索引 获取list中的值

LSET key index value

set(key, index, value)

根据索引修改list中的某条数据

LREM key count value

remove(key, count, value)

移除N个值为value

leftPop(key)

该函数用于移除上面我们抽象的容器中的最左边的一个元素。

rightPop(key)

该函数用于移除上面我们抽象的容器中的最右边的一个元素。

7.Set相关的操作

redisTemplate.opsForSet(); //操作Set类型

操作Redis命令

StringRedisTemplate/RedisTemplate

说明

SMEMBEredisTemplate key

memberedisTemplate(key)

根据key获取Set中的所有值

SISMEMBER key value

isMember(key, value)

根据value从一个set中查询,是否存在

SADD key value1 value2

add(key, values)

将数据放入set缓存

SCARD key

size(key)

获取set缓存的长度

SREM key value1 value2

remove(key, values)

移除值为value的

SDIFF key1, key2

difference(key1, key2)

求两个key对应的set的差集(不包括右边的)

SINTER key1, key2

intersect(key1, key2)

求两个key对应的set的交集

SUNION key1, key2

set.union(key1, key2)

求两个key对应的set的并集

8.ZSet相关的操作

redisTemplate.opsForZSet(); //操作ZSet(有序集合)类型

9.示例操作

package com.kang.redis.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author Emperor Kang
 * @ClassName RedisController
 * @Description TODO
 * @Date 2022/8/11 14:36
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@RestController
@Slf4j
public class RedisController {
    public static final String key1 = "student#03";
    public static final String key2 = "student#04";
    public static final String key = "student#05";

    @Autowired
    private StringRedisTemplate redisTemplate;

    @GetMapping("/string")
    public void redisForString() throws InterruptedException {
        test1();
        test2();
        test3();
        test4();
    }

    @GetMapping("/hashmap")
    public void redisForHashMap() throws InterruptedException {
        test5();
        test6();
        test7();
    }

    @GetMapping("/list")
    public void redisForList() throws InterruptedException {
        test8();
    }

    @GetMapping("/set")
    public void redisForSet() throws InterruptedException {
        test9();
    }

    @GetMapping("/ZSet")
    public void redisForZSet() throws InterruptedException {
        test10();
    }

    /**
     * 操作ZSet
     */
    private void test10() {
        //添加周星星同学成绩
        redisTemplate.opsForZSet().add(key,"语文",98);
        redisTemplate.opsForZSet().add(key,"数学",87);
        redisTemplate.opsForZSet().add(key,"英语",75);
        //获取分数最高的成绩
        ZSetOperations.TypedTuple<String> values = redisTemplate.opsForZSet().popMax(key);
        //打印值
        log.info("周星星最好成绩科目是:"+values.getValue());
        log.info("周星星最好成绩:"+values.getScore());
        log.info("======================================================================");
    }

    /**
     * 操作set
     */
    private void test9() {
        SetOperations<String, String> set = redisTemplate.opsForSet();
        set.add(key1,"a");
        set.add(key1,"b");
        set.add(key1,"c");

        set.add(key2,"b");
        set.add(key2,"c");
        set.add(key2,"d");

        System.out.println("key1 = " + set.members(key1));
        System.out.println("key2 = " + set.members(key2));

        log.info("set.difference(key1,key2) = " + set.difference(key1, key2));
        log.info("set.intersect(key1,key2) = " + set.intersect(key1, key2));
        log.info("set.union(key1,key2) = " + set.union(key1, key2));
        log.info("======================================================================");
    }

    /**
     * 操作list
     */
    private void test8() {
        redisTemplate.opsForList().leftPush(key,"周星星");
        redisTemplate.opsForList().leftPush(key, "张敏");
        redisTemplate.opsForList().leftPush(key, "李大锤");
        String value = redisTemplate.opsForList().rightPop(key);
        String value2 = redisTemplate.opsForList().leftPop(key);
        log.info("从list的右边获取数据:{}",value);
        log.info("从list的左边获取数据:{}",value2);
        log.info("当前list的长度为:{}",redisTemplate.opsForList().size(key));
        log.info("======================================================================");
    }

    /**
     * 获取长度
     */
    private void test7() {
        Long length = redisTemplate.opsForHash().lengthOfValue(key, "id");
        log.info("获取map中指定值的长度:{}",length);
        log.info("======================================================================");
    }

    /**
     * 获取所有的值
     */
    private void test6() {
        List<Object> values = redisTemplate.opsForHash().values(key);
        log.info("获取map中所有的值:{}",values);
        log.info("======================================================================");
    }

    /**
     * 操作hashmap
     */
    private void test5() {
        redisTemplate.opsForHash().put(key,"id","001");
        redisTemplate.opsForHash().put(key,"name","张三");
        redisTemplate.opsForHash().put(key,"age","18");
        redisTemplate.opsForHash().put(key,"sex","男");
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);
        log.info("获取所有的键值对:{}",entries);
        log.info("======================================================================");
    }

    /**
     * 不带过期时间
     */
    private void test1() {
        redisTemplate.opsForValue().set("name","看看有什么不好呢");
        String name = redisTemplate.opsForValue().get("name");
        log.info("name:{}",name);
        log.info("======================================================================");
    }

    /**
     * 带过期时间
     * @throws InterruptedException
     */
    private void test2() throws InterruptedException {
        redisTemplate.opsForValue().set("name","我不看",5, TimeUnit.SECONDS);
        String name = redisTemplate.opsForValue().get("name");
        log.info("第1次获取name:{}",name);

        Thread.sleep(6000);

        String name2 = redisTemplate.opsForValue().get("name");
        log.info("第2次获取name:{}",name2);
        log.info("======================================================================");
    }

    /**
     * ValueOperations<String, String>
     */
    private void test3() {
        ValueOperations<String, String> value = redisTemplate.opsForValue();
        log.info("ValueOperations<String, String>.get()={}",value.get("p1"));
        log.info("======================================================================");
    }

    /**
     * 将 key 的值设为 value ,当且仅当 key 不存在
     */
    private void test4() {
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("name", "看看有什么不好呢");
        Boolean aBoolean1 = redisTemplate.opsForValue().setIfAbsent("name", "我不看");
        System.out.println("aBoolean = " + aBoolean);
        System.out.println("aBoolean1 = " + aBoolean1);
        log.info("======================================================================");
    }
}

10.RedisTemplate使用String序列化配置

package com.kang.redis.config;

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.RedisSerializer;

/**
 * @Author Emperor Kang
 * @ClassName RedisConfig
 * @Description redis配置类
 * @Date 2022/8/11 11:17
 * @Version 1.0
 * @Motto 让营地比你来时更干净
 */
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setValueSerializer(RedisSerializer.string());

        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        redisTemplate.setHashValueSerializer(RedisSerializer.string());

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}