赞
踩
Spring 封装了 RedisTemplate 来操作 Redis,它支持所有的 Redis 原生的 API。在 RedisTemplate 中定义了对5种数据结构的操作方法。
opsForValue():操作字符串。
opsForList():操作列表。
opsForHash():操作哈希。
opsForSet():操作集合。
opsForZSet():操作有序集合。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<!--pringDataRedis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
server:
port: 8080
spring:
application:
name: redisTemplate
#redis默认配置
redis:
host: 116.62.13.104
本Demo在测试类中操作Redis的五种数据类型
解决方法:
/**
* 指定序列化方式
* 如果不指定序列化方式
* String类型存入到Redis中会 : \xAC\xED\x00\x05t\x00\x09Stringkey
*/
@PostConstruct
public void init() {
RedisSerializer redisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(redisSerializer);
redisTemplate.setValueSerializer(redisSerializer);
redisTemplate.setHashKeySerializer(redisSerializer);
redisTemplate.setHashValueSerializer(redisSerializer);
}
package com.lsh.config;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author :LiuShihao
* @date :Created in 2021/2/18 9:52 上午
* @desc :配置类 RedisCacheConfig
* 默认情况下的模板只能支持 RedisTemplate<String, String>,也就是只能存入字符串,所以自定义模板很有必要。
*/
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisCacheConfig {
@Bean
public RedisTemplate<String, String> redisCacheTemplate(LettuceConnectionFactory connectionFactory) {
System.out.println("RedisTemplate加载...");
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
RedisSerializer redisSerializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(redisSerializer);
redisTemplate.setValueSerializer(redisSerializer);
redisTemplate.setHashKeySerializer(redisSerializer);
redisTemplate.setHashValueSerializer(redisSerializer);
redisTemplate.setConnectionFactory(connectionFactory);
return redisTemplate;
}
}
使用时注入
@Autowired
private RedisTemplate<String, String> redisCacheTemplate;
/**
* redisTemplate.opsForValue() 操作String类型 Key-Value 键值对
* 使用set(K key, V value) 存入
*
* get(K key) 取出
*
* set(K key, V value, long timeout, TimeUnit unit) 设置失效时间
*
* redisTemplate.opsForValue().getAndSet(K key, V value); 获得旧值并重新放入新值
*/
@Test
public void test1(){
init();
redisTemplate.opsForValue().set("Stringkey1","StringValue1");
redisTemplate.opsForValue().set("Stringkey2","StringValue2",120, TimeUnit.SECONDS);
System.out.println(redisTemplate.opsForValue().get("Stringkey1"));
System.out.println(redisTemplate.opsForValue().get("Stringkey2"));
redisTemplate.opsForValue().getAndSet("Stringkey1","StringValue11");
System.out.println(redisTemplate.opsForValue().get("Stringkey1"));
}
Redis 中的 hash(哈希)是一个 string 类型的 field
和 value
的映射表,hash 特别适合用于存储对象。value 中存放的是结构化的对象。利用这样数据结果,可以方便地操作其中的某个字段。比如在“单点登录”时,可以用这种数据结构存储用户信息。以 CookieId 作为 key,设置30分钟为缓存过期时间,能很好地模拟出类似 Session 的效果。
/**
* redisTemplate.opsForHash()操作Hash结构
*
* putAll(K key,Map map)直接Map存入
* entries(K key) 取出
* void put(H key, HK hashKey, HV value) 存入单个字段
*
* HV get(H key, Object hashKey) 获得Hash类型的单个字段
*/
@Test
public void test3(){
init();
HashMap<String, String> map = new HashMap<>();
map.put("id","1");
map.put("name","LiuShihao");
map.put("age","24");
map.put("job","Police");
// redisTemplate.opsForHash().putAll("userHash",map);
System.out.println(redisTemplate.opsForHash().entries("userHash"));
// redisTemplate.opsForHash().put("userHash2","id","1");
// redisTemplate.opsForHash().put("userHash2","name","aaa");
// redisTemplate.opsForHash().put("userHash2","age","24");
// redisTemplate.opsForHash().put("userHash2","job","美团外卖");
System.out.println(redisTemplate.opsForHash().get("userHash2","id"));
System.out.println(redisTemplate.opsForHash().get("userHash2","name"));
System.out.println(redisTemplate.opsForHash().get("userHash2","age"));
System.out.println(redisTemplate.opsForHash().get("userHash2","job"));
//获取整个Hash类型的key
System.out.println(redisTemplate.opsForHash().keys("userHash2"));
//获取整个Hash类型的value
System.out.println(redisTemplate.opsForHash().values("userHash2"));
}
Redis列表是简单的字符串列表,按照插入顺序排序
。可以添加一个元素到列表的头部(左边)或尾部(右边)。
使用list数据结构,可以做简单的消息队列
的功能。还可以利用 Irange 命令,做基于Reids的分页
功能,性能极佳。
/**
* redisTemplate.opsForList() 操作List类型
* leftPushAll:向一个key中直接插入字符数组
* range:获得一个list中的 所有字段信息 第一个索引是0, 最后一个索引是-1
* rightPush:向一个List中插入单个字段
* index: 根据索引获得list中的字段
*
* leftPop方法:弹出最左边的元素,弹出之后该值在列表中将不复存在。
*
* rightPop方法:弹出最右边的元素,弹出之后该值在列表中将不复存在。具体用法见以下代码:
*/
@Test
public void test2(){
init();
String[] user1 = new String[]{"1","zs","19","程序员"};
//向一个key中直接插入字符数组
redisTemplate.opsForList().leftPushAll("user1-leftPushAll",user1);
redisTemplate.opsForList().rightPushAll("user1-rightPushAll",user1);
// 获得一个list中的 所有字段信息 第一个索引是0, 最后一个索引是-1
System.out.println(redisTemplate.opsForList().range("user1-leftPushAll",0,-1));
System.out.println(redisTemplate.opsForList().range("user1-rightPushAll",0,-1));
//向一个key中插入单个字段
redisTemplate.opsForList().rightPush("user2-rightPush","1");
redisTemplate.opsForList().rightPush("user2-rightPush","ls");
redisTemplate.opsForList().rightPush("user2-rightPush","20");
redisTemplate.opsForList().rightPush("user2-rightPush","教师");
// 根据索引获得list中的一个key中的第几个字段
System.out.println(redisTemplate.opsForList().index("user2-rightPush",0));
System.out.println(redisTemplate.opsForList().index("user2-rightPush",1));
System.out.println(redisTemplate.opsForList().index("user2-rightPush",2));
System.out.println(redisTemplate.opsForList().index("user2-rightPush",3));
String[] user3 = new String[]{"3","ww","28","警察"} ;
redisTemplate.opsForList().rightPushAll("user3",user3);
System.out.println(redisTemplate.opsForList().range("user3",0,-1));
//弹出最右边的元素,弹出之后该值在列表中将不复存在
System.out.println(redisTemplate.opsForList().rightPop("user3"));
System.out.println(redisTemplate.opsForList().range("user3",0,-1));
}
set 是存放不重复值
的集合。利用 set 可以做全局去重复的功能。还可以进行交集、并集、差集等操作,也可用来实现计算共同喜好、全部的喜好、自己独有的喜好等功能。
Redis 的 set 是 string 类型的无序集合
,通过散列表实现。
/**
* 使用redisTemplate.opsForSet() 操作Set类型
* add方法:在无序集合中添加元素,返回添加个数;如果存在重复的则不进行添加。
*
* members方法:返回集合中的所有成员。
*
* Long remove(K key, Object... values) 移除集合中一个或多个成员。
*
* scan 遍历Set集合
*
* Set<V> intersect(K key1, K key2)方法、Long intersectAndStore(K key1, K key2, K destKey)方法:交集。
*
* Set<V> union(K key1, K key2)方法、Long unionAndStore(K key1, K key2, K destKey)方法:并集。
*
* Set<V> difference(K key1, K key2)方法、Long differenceAndStore(K key1, K key2, K destKey)方法:差集。
*/
@Test
public void test4(){
init();
String[] citys = new String[] {"北京","上海","广州","深圳"};
// redisTemplate.opsForSet().add("citySet",citys);
System.out.println(redisTemplate.opsForSet().members("citySet"));
// redisTemplate.opsForSet().add("citySet","郑州","北京","上海");
// System.out.println(redisTemplate.opsForSet().members("citySet"));
//remove 移除一个或多个元素
// System.out.println(redisTemplate.opsForSet().remove("citySet","广州"));
// System.out.println(redisTemplate.opsForSet().members("citySet"));
// 遍历Set
Cursor citySet = redisTemplate.opsForSet().scan("citySet", ScanOptions.NONE);
while(citySet.hasNext())
{
System.out.println(citySet.next());
}
redisTemplate.opsForSet().add("CitysSet1","北京","武汉","石家庄","郑州","西安","济南");
redisTemplate.opsForSet().add("CitysSet2","上海","浙江","南京","郑州","香港","北京");
//交集
redisTemplate.opsForSet().intersectAndStore("CitysSet1","CitysSet2","CitysSetIntersectAndStore");
//并集
redisTemplate.opsForSet().unionAndStore("CitysSet1","CitysSet2","CitysSetUnionAndStore");
//差集 的意思是 对CitysSet1求CitysSet2的差集 返回的结果:[石家庄, 西安, 济南, 武汉] 代表的是1中有2中没有的元素
redisTemplate.opsForSet().differenceAndStore("CitysSet1","CitysSet2","CitysSetDifferenceAndStore");
System.out.println(redisTemplate.opsForSet().members("CitysSetIntersectAndStore"));
System.out.println(redisTemplate.opsForSet().members("CitysSetUnionAndStore"));
System.out.println(redisTemplate.opsForSet().members("CitysSetDifferenceAndStore"));
}
zset(Sorted Set 有序集合)也是 string 类型元素的集合,且不允许重复
的成员。每个元素都会关联一个 double 类型的分数。可以通过分数将该集合中的成员从小到大进行排序。
zset 的成员是唯一的,但权重参数分数(score)
却可以重复。集合中的元素能够按 score 进行排列。它可以用来做排行榜应用、取TOP/N、延时任务、范围查找等。
第一种添加方式:
第二种添加方式:
/**
* zset(Sorted Set 有序集合)也是 string 类型元素的集合,且不允许重复的成员。每个元素都会关联一个 double 类型的分数。可以通过分数将该集合中的成员从小到大进行排序。
*
* zset 的成员是唯一的,但权重参数分数(score)却可以重复。集合中的元素能够按 score 进行排列。它可以用来做排行榜应用、取TOP/N、延时任务、范围查找等。
*
* 使用redisTemplate.opsForZSet() 操作ZSet集合
* Boolean add(K var1, V var2, double var3);
* Long add(K key, Set<ZSetOperations.TypedTuple<V>> tuples) 增加一个有序集合
*
* Long remove(K key, Object... values) 从有序集合中移除一个或者多个元素
*
* Set<V> range(K KET, long var2, long var4); 查看ZSet集合中的元素
*
* Long rank(K key, Object value) 返回有序集中指定成员的排名,其中有序集成员按分数值递增(从小到大)顺序排列
*
* rank 返回有序集中指定成员的排名, 其中有序集成员按分数值递增(从小到大)顺序排列
*
* range方法:通过索引区间返回有序集合成指定区间内的成员,其中有序集成员按分数值递增(从小到大)顺序排列。
*
* rangeByScore方法:通过分数区间返回有序集合成指定区间内的成员,其中有序集成员按分数值递增(从小到大)顺序排列。
*
* count方法:通过分数返回有序集合指定区间内的成员个数。
*
* size方法:获取有序集合的成员数。
*/
@Test
public void test5(){
ZSetOperations.TypedTuple<String> objectTypedTuple1 = new DefaultTypedTuple<>("肖申克的救赎",9.7);
ZSetOperations.TypedTuple<String> objectTypedTuple2 = new DefaultTypedTuple<>("霸王别姬",9.6);
ZSetOperations.TypedTuple<String> objectTypedTuple3 = new DefaultTypedTuple<>("阿甘正传",9.5);
ZSetOperations.TypedTuple<String> objectTypedTuple4 = new DefaultTypedTuple<>("这个杀手不太冷",9.4);
ZSetOperations.TypedTuple<String> objectTypedTuple5 = new DefaultTypedTuple<>("冷血狂宴 / 爵迹2",4.0);
Set<ZSetOperations.TypedTuple<String>> movie = new HashSet<ZSetOperations.TypedTuple<String>>();
movie.add(objectTypedTuple1);
movie.add(objectTypedTuple2);
movie.add(objectTypedTuple3);
movie.add(objectTypedTuple4);
movie.add(objectTypedTuple5);
redisTemplate.opsForZSet().add("movie",movie);
//通过索引区间返回有序集合成指定区间内的成员,其中有序集成员按分数值递增(从小到大)顺序排列。
System.out.println(redisTemplate.opsForZSet().range("movie",0,-1));
redisTemplate.opsForZSet().add("StudentZSet","99",9.9);
redisTemplate.opsForZSet().add("StudentZSet","80",8.0);
redisTemplate.opsForZSet().add("StudentZSet","69",6.9);
redisTemplate.opsForZSet().add("StudentZSet","52",5.4);
redisTemplate.opsForZSet().add("StudentZSet","32",3.4);
redisTemplate.opsForZSet().add("StudentZSet","23",1.9);
System.out.println(redisTemplate.opsForZSet().range("StudentZSet",0,-1));
// 移除ZSet中的一个或多个元素
redisTemplate.opsForZSet().remove("StudentZSet","69");
System.out.println("移除ZSet中的一个或多个元素:"+redisTemplate.opsForZSet().range("StudentZSet",0,-1));
//返回有序集中指定成员的排名, 其中有序集成员按分数值递增(从小到大)顺序排列
System.out.println("返回有序集中指定成员的排名:"+redisTemplate.opsForZSet().rank("movie", "阿甘正传"));
//通过分数区间返回有序集合成指定区间内的成员,其中有序集成员按分数值递增(从小到大)顺序排列。
System.out.println("通过分数区间返回有序集合成指定区间内的成员:"+redisTemplate.opsForZSet().rangeByScore("StudentZSet", 3, 8));
System.out.println("分数在0至8区间内的成员个数:" + redisTemplate.opsForZSet().count("StudentZSet", 3, 8));
System.out.println("movie有序集合的成员数:" + redisTemplate.opsForZSet().size("movie"));
System.out.println("获取指定成员的score值:" + redisTemplate.opsForZSet().score("movie", "这个杀手不太冷"));
// 遍历 zset
Cursor<ZSetOperations.TypedTuple<Object>> cursor = redisTemplate.opsForZSet().scan("movie",ScanOptions.NONE);
while (cursor.hasNext()){
ZSetOperations.TypedTuple<Object> next = cursor.next();
//System.out.println(next); // 打印的对象地址 org.springframework.data.redis.core.DefaultTypedTuple@35698b75
System.out.println(next.getValue() + " 的分数值:" + next.getScore());
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。