01
前言
在springboot项目中我们经常使用redisTemplate来操作Redis,完成对数据的保存与查询。接下来将分别展示对redis的5种数据类型string/list/set/zset/hash的数据的操作。并且对这些数据类型的使用场景作简单分析。欢迎大家留言交流探讨
02
redisTemplate的基本配置
application.yml文件中配置Redis的连接地址:
spring:## redis 配置redis:host: 192.168.28.200port: 6379
使用redisTemplate需要首先在spring容器中初始化该配置类,配置主要是对key和value序列化的方式进行设定,这里的key和value分别采用string,object的数据类型,key使用string序列化方式,value使用json序列化方式,这样可以基本满足绝大部分的使用场景。配置类如下:
@Configurationpublic class RedisTemplateConfig {@Bean@Primarypublic RedisTemplate<String,Object> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory){RedisTemplate<String,Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);// key 的序列化方式为 string 序列化方式template.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());template.setValueSerializer(fastJsonRedisSerializer);template.setHashValueSerializer(fastJsonRedisSerializer);template.setDefaultSerializer(fastJsonRedisSerializer);template.afterPropertiesSet();return template;}}
再使用时通过@Autowired 注入redisTemplate 即可;
@Autowiredprivate RedisTemplate<String,Object> redisTemplate;
03
不同数据类型的保存与获取
1)
string
Redis最基本的数据类型,是一个单独的字符串,设定key value即可,比如key是“country” value是 “中华人民共和国”。使用redisTemplate.opsForValue() 使用set(key,value) get(key)即可。我们来看下java代码:
redisTemplate.opsForValue().set(RedisConstantKey.MY_REDIS_VALUE.key,"中华人民共和国");Object o = redisTemplate.opsForValue().get(RedisConstantKey.MY_REDIS_VALUE.key);if(Objects.nonNull(o)){System.out.println(o.toString());}
2)
List
类似Java中的list列表,可以完成对一个数组数据的存储,获取时也可以根据索引获取
比如我们的key为编程语言language,value为 {"java","c++","python","js"}等一些列具体的编程语言,类似这样的数据结构就非常适合用list来存储,我们来看下用redisTemplate如何操作:
public void setRedisList(){List<Object> language = Lists.newArrayList("java","c++","python","js");redisTemplate.opsForList().leftPushAll(RedisConstantKey.MY_REDIS_LIST.key,language);}public void getRedisList(){List<Object> languageList = redisTemplate.opsForList().range(RedisConstantKey.MY_REDIS_LIST.key, 0, -1);// 可以直接转换成stringif(CollectionUtils.isNotEmpty(languageList)){List<String> languageStrs = languageList.stream().map(String::valueOf).collect(Collectors.toList());System.out.println("遍历输出到表中!");languageStrs.forEach(System.out::println);}}遍历输出到表中!jspythonc++java
使用opsForList这个api操作list,入库的时候可以leftPush 也可以rightPush,取出的时候使用range(),后面的索引0 为从最左边开始的索引,-1 为最右边开始的索引,0,-1 代表取出列表中的所有数据。从左边插入过程如下所示:-> java; -> c++ -> java; -> python -> c++ -> java; js -> python -> c++ -> java; 所以最后的列表就是: js -> python -> c++ -> java。那么取出来之后就是上述结果。
3)
set
set集合类似数学中的集合,是不能有重复数据的,这和Java中的Set数据结构也是一致的,如果后面插入了和前面相同的数据,则会自动去重。我们来看下redisTemplate的操作示例,这里使用的是redisTemplate.opsForSet(), 取出数据时,可以直接使用members()取出所有的数据 ,通过输出打印,我们发现存入的两个aa 输出时只有一个了,已经被自动去重了。
/*** 无序集合,不可重复*/public void setRedisSet(){redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"aa");redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"bb");redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"cc");// 这里加入一个重复的值,set集合自动去重redisTemplate.opsForSet().add(RedisConstantKey.MY_REDIS_SET.key,"aa");}public void getRedisSet(){Set<Object> members = redisTemplate.opsForSet().members(RedisConstantKey.MY_REDIS_SET.key);Iterator<Object> it = members.iterator();while (it.hasNext()){System.out.println(it.next());}}result:bbccaa
4)
zset
有时候我们需要存储一个有序的集合,比如大学的排名等,这个排行榜可能随时刷新,使用redis的有序集合来存储是非常合适的。redisTemplate.opsForZset()api 就是专门用来操作有序集合的。它排序的规则是根据入库的分数来计算的,在数据库里的存储顺序按照分数从小到大的顺序进行排序。取出的时候可以按照分数段区间取出,也可以按照正序或者倒序的顺序取出,比如示例代码里面获取排行榜前三位和后三位的学校。
public void setRedisZset(){redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"Harvard大学",100);redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"中山大学",80);redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"清华大学",98);redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"北京大学",99);redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"复旦大学",87);redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"上海大学",76);redisTemplate.opsForZSet().add(RedisConstantKey.MY_REDIS_ZSET.key,"西藏大学",63);}public void getRedisZset(){Set<Object> range1 = redisTemplate.opsForZSet().rangeByScore(RedisConstantKey.MY_REDIS_ZSET.key, 90, 100);range1.forEach((v) -> System.out.println("90分以上的大学: "+v));System.out.println("=====================================================");Set<Object> range2 = redisTemplate.opsForZSet().rangeByScore(RedisConstantKey.MY_REDIS_ZSET.key, 80, 100);range2.forEach((v) -> System.out.println("80分以上的大学: "+v));System.out.println("=====================================================");Set<Object> range3 = redisTemplate.opsForZSet().rangeByScore(RedisConstantKey.MY_REDIS_ZSET.key, 0, 100);range3.forEach((v) -> System.out.println("60分以上的大学: "+v));System.out.println("排名后三位的大学:::");Set<Object> rank = redisTemplate.opsForZSet().range(RedisConstantKey.MY_REDIS_ZSET.key, 0, 2);rank.forEach(System.out::println);System.out.println("排名前三位的大学:::");Set<Object> rank2 = redisTemplate.opsForZSet().reverseRange(RedisConstantKey.MY_REDIS_ZSET.key, 0, 2);rank2.forEach(System.out::println);}result:90分以上的大学: 清华大学90分以上的大学: 北京大学90分以上的大学: Harvard大学=====================================================80分以上的大学: 中山大学80分以上的大学: 复旦大学80分以上的大学: 清华大学80分以上的大学: 北京大学80分以上的大学: Harvard大学=====================================================60分以上的大学: 西藏大学60分以上的大学: 上海大学60分以上的大学: 中山大学60分以上的大学: 复旦大学60分以上的大学: 清华大学60分以上的大学: 北京大学60分以上的大学: Harvard大学排名后三位的大学:::西藏大学上海大学中山大学排名前三位的大学:::Harvard大学北京大学清华大学本次请求的时间为:23
5)
hash
hash 是一个string 类型的 field 和 value的映射表,hash特别适合于存储对象。使用redisTemplate.opsForHash()这个api分别存入多个字段。取出的时候可以使用entries()取出所有的字段,也可以根据需要取出该key下面的特定field的value,直接使用get()api即可,具体参考下面的示例代码:
public void setRedisHash(){Map<String,String> nameAgeMap = new HashMap<>();nameAgeMap.put("name","alice");nameAgeMap.put("address","beijing");nameAgeMap.put("age","18");redisTemplate.opsForHash().putAll(RedisConstantKey.MY_REDIS_HASH.key,nameAgeMap);}public void getRedisHash(){Map<Object,Object> nameAgeMap = redisTemplate.opsForHash().entries(RedisConstantKey.MY_REDIS_HASH.key);nameAgeMap.forEach((k,v)->{System.out.println("k==="+k+"v==="+v);});Object o = redisTemplate.opsForHash().get(RedisConstantKey.MY_REDIS_HASH.key,"name");System.out.println("name是:"+o);}result:k===:address v===:beijingk===:name v===:alicek===:age v===:18name是:alice
04
小结
针对redis中经常使用到的string、list、set、zset、hash 等5种数据类型分别进行归纳分析,在实际项目中,首先应该分析业务场景找到最适合的数据结构类型再进行存储,这样往往可以达到事半功倍的效果。在Java项目中使用redisTemplate可以方便的实现对这5种数据类型的保存与获取(查询)。文章也提到了这些数据类型的常见使用场景。





扫二维码|关注我们




