SpringBoot使用RedisTemplate簡單操作Redis的五種資料型別
一、介紹
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結構
本Demo在測試類中操作Redis的五種資料型別
Bug
解決方法:
/** * 指定序列化方式 * 如果不指定序列化方式 * 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); }
操作五種資料型別
1.String型別
/** * 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")); }
2.Hash型別
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"));
}
3.List型別
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));
}
4.Set型別
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"));
}
5.ZSet型別
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());
}
}