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;
}
}