SpringBoot整合Redis 之 StringRedisTemplate、RedisTemplate 基礎

Spring Boot Data(數據) Redis 中提供了 RedisTemplate StringRedisTemplate

StringRedisTemplateRedisTemplate 的子類,兩個方法基本一致,不同之處在於 操作的數據類型不同

  • RedisTemplate 兩個泛型都是 Object,意味着存儲的 key 和 value 都可以是一個對象
  • StringRedisTemplate 兩個泛型都是 String,意味着存儲的 的 key 和 value 都只能是字符串。

注:使用 RedisTemplate 默認是將對象序列化到 Redis 中,所以 放入的對象必須實現對象序列化接口

注:兩者的 數據是不共通的;也就是說 StringRedisTemplate 只能管理 StringRedisTemplate 裏面的數據,RedisTemplate 只能管理 RedisTemplate 中的數據。

環境準備

引入依賴

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置文件

# 連接有redis服務的主機
spring.redis.host=localhost 
spring.redis.port=6379
spring.redis.database=0

StringRedisTemplate 基本使用

API 是學不完的,掌握一些基本操作,其他操作有需要再查詢即可!

StringRedisTemplate.opsForValue();	// 操作字符串
StringRedisTemplate.opsForHash(); 	// 操作hash
StringRedisTemplate.opsForList(); 	// 操作list
StringRedisTemplate.opsForSet();  // 操作set
StringRedisTemplate.opsForZSet(); 	// 操作有序set

通過@Autowired註解的方式注入 StringRedisTemplate 對象:

@Autowired
private StringRedisTemplate stringRedisTemplate;  // key, value 都是字符串

Key 常用操作

刪除一個 key:

stringRedisTemplate.delete("name"); // 刪除一個key

刪除當前 redis 庫中所有鍵值對:

// 刪除當前redis庫中所有鍵值對
Set<String> keys = stringRedisTemplate.keys("*"); // 查詢出所有的鍵
stringRedisTemplate.delete(keys);

判斷某個 key 是否存在,判斷 key 所對應值的類型:

Boolean hasKey = stringRedisTemplate.hasKey("name"); // 判斷某個key是否存在
DataType type = stringRedisTemplate.type("name"); // 判斷key對應的值的類型

獲取 key 超時時間(-1 永不超時,-2 key不存在,>=0 過期時間)

Long expire = stringRedisTemplate.getExpire("name");

在 redis 中隨機獲取一個 key:

String randomKey = stringRedisTemplate.randomKey();

修改 key 的名字,要求 key 必須存在,不存在則拋出異常:

stringRedisTemplate.rename("name", "newname");
// stringRedisTemplate.renameIfAbsent("age", "newname");

將指定 key 移動到 指定庫:

stringRedisTemplate.move("newname", 1); 

String 常用操作

所有字符串的操作都是通過 StringRedisTemplate.opsForValue(); 實現。

設置一個 key value:

stringRedisTemplate.opsForValue().set("name", "振宇"); // set 用來設置一個key value

獲取一個 key 對應 value:

String value = stringRedisTemplate.opsForValue().get("name");

設置一個 key 超時時間

// key:code  value:2537  超時時間:120s 
stringRedisTemplate.opsForValue().set("code", "2537", 120, TimeUnit.SECONDS); 

往指定鍵的值後面 追加 字符串:

stringRedisTemplate.opsForValue().append("name", "他是一個好人!");

List 常用操作

所有 List 的操作都是通過 StringRedisTemplate.opsForList(); 實現。

從左邊往列表中放入一個元素:

stringRedisTemplate.opsForList().leftPush("lists", "振宇");

從左邊往列表中放入多個元素(兩種方法):

stringRedisTemplate.opsForList().leftPushAll("lists", "張三", "李四", "王五");
List<String> names = new ArrayList<>();
names.add("xiaoming");
names.add("xiaosan");
stringRedisTemplate.opsForList().leftPushAll("lists", names);

遍歷整個 List:

List<String> stringList = stringRedisTemplate.opsForList().range("lists", 0, -1);// 遍歷list
stringList.forEach(v -> System.out.println("value = " + v));

保留截取的指定區間的 List:

stringRedisTemplate.opsForList().trim("lists", 1, 3);

Set 常用操作

所有 Set 的操作都是通過 StringRedisTemplate.opsForSet(); 實現。

創建 Set 並放入多個元素:

stringRedisTemplate.opsForSet().add("sets", "張三", "張三", "李四", "振宇"); // 創建set 並放入多個元素

查看 Set 中所有成員:

Set<String> sets = stringRedisTemplate.opsForSet().members("sets");
sets.forEach(value -> System.out.println("value = " + value));

獲取 Set 中元素個數:

Long size = stringRedisTemplate.opsForSet().size("sets");

ZSet 常用操作

所有 ZSet 的操作都是通過 StringRedisTemplate.opsForZSet(); 實現。

創建 ZSet 並放入元素:

stringRedisTemplate.opsForZSet().add("zsets", "小黑", 20);

指定範圍進行查詢:

// 遍歷所有元素
Set<String> zsets = stringRedisTemplate.opsForZSet().range("zsets", 0, -1);
zsets.forEach(value-> System.out.println(value));

獲取指定元素以及分數(可以指定分數範圍):

// 獲取分數範圍在 0 -1000 之間的元素 並排序
Set<ZSetOperations.TypedTuple<String>> zsets1 = stringRedisTemplate.opsForZSet().rangeByScoreWithScores("zsets", 0, 1000);
zsets1.forEach(typedTuple ->{
	System.out.println("value = " + typedTuple.getValue() + ", score = " + typedTuple.getScore());
});

Hash 常用操作

所有 Hash 的操作都是通過 StringRedisTemplate.opsForHash(); 實現。

往指定 Hash 中放入一個 key,value:

stringRedisTemplate.opsForHash().put("maps", "name", "zhangsan");

往指定 Hash 中放入多個 key,value:

 Map<String, String> map = new HashMap<>();
map.put("age", "12");
map.put("bir", "2012-12-12");
stringRedisTemplate.opsForHash().putAll("maps", map); // 放入多個key, value

獲取指定 Hash 中某個 key 的 value:

String value = (String) stringRedisTemplate.opsForHash().get("maps", "name");

獲取指定 Hash 中多個 key 的 value:

List<Object> values = stringRedisTemplate.opsForHash().multiGet("maps", Arrays.asList("name", "age"));
values.forEach(value -> System.out.println(value));

獲取指定 Hash 中所有 key,獲取所有 value:

Set<Object> keys = stringRedisTemplate.opsForHash().keys("maps"); // 獲取所有keys
List<Object> vals = stringRedisTemplate.opsForHash().values("maps"); // 獲取所有values

Key 的綁定操作 Bound

Spring Data 爲了方便我們對 redis 進行更友好的操作,提供了 bound api 簡化操作。

如果日後對某一個 key 的操作極其頻繁,可以將這個 key 綁定到對應 redistemplate 中,可以簡化操作。

  • boundValueOps 用來對 String 值綁定 key
  • boundListOps 用來對 List 值綁定 key
  • boundSetOps 用來對 Set 值綁定 key
  • boundZSetOps 用來對 ZSet 值綁定 key
  • boundHashOps 用來對 Hash 值綁定 key

原本代碼可能需要這麼寫:

stringRedisTemplate.opsForValue().set("name", "zhangsan");
stringRedisTemplate.opsForValue().append("name", "是一個好人");
String s = stringRedisTemplate.opsForValue().get("name");
System.out.println(s);

綁定後只需要這麼寫:

BoundValueOperations<String, String> nameValueOperations = stringRedisTemplate.boundValueOps("name");

nameValueOperations.set("zhangsan");
nameValueOperations.append("是一個好人");
String name = nameValueOperations.get();

對 List 進行綁定:

BoundListOperations<String, String> listsOperations = stringRedisTemplate.boundListOps("lists");
listsOperations.leftPushAll("張三", "李四", "小陳");
List<String> lists = listsOperations.range(0, -1);
lists.forEach(list-> System.out.println(list));

redis 中每個數據類型都可以進行綁定,與上面同理。

RedisTemplate 基本使用

RedisTemplate 的用法和 StringRedisTemplate 基本一樣,我們關注他們的不同之處!

RedisTemplateStringRedisTemplate 的區別主要在於他們使用的序列化類:

  • RedisTemplate 使用的是 JdkSerializationRedisSerializer,存入數據時,會將數據先序列化成字節數組,然後再存入 Redis 數據庫。;
  • StringRedisTemplate 使用的是 StringRedisSerializer

通過@Autowired註解的方式注入 RedisTemplate 對象:

@Autowired
private RedisTemplate redisTemplate;  //存儲對象

想要存入 redis 的對象必須實現序列化接口:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class User implements Serializable { // 實現序列化接口
    private String id;
    private String name;
    private Integer age;
    private Date bir;
}

RedisTemplate 基本操作

往 redis 中存入一個 User 對象:

redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); // 指定值使用對象序列化
// 往redis中存入一個User對象
redisTemplate.opsForValue().set("user", new User("21", "小黑", 23, new Date()));
// 根據值獲取存入的User對象
User user = (User) redisTemplate.opsForValue().get("user");
System.out.println(user);

需要注意的是,如果通過 redis 客戶端查看其中的數據,無法正常顯示 key 名,如下圖:
在這裏插入圖片描述
在這裏插入圖片描述

RedisTemplate 正常往 redis 中存入 String 數據與 StringRedisTemplate 用法幾乎一樣,但是如果存放的是 String 類型數據則更推薦 StringRedisTemplate 而不是 RedisTemplate

redisTemplate.opsForList().leftPushAll("lists", "hello", "world");
List lists = redisTemplate.opsForList().range("lists", 0, -1);
lists.forEach(list -> System.out.println(list));

RedisTemplate 與 StringRedisTemplate 數據互不相通

RedisTemplate 和 StringRedisTemplate 的數據是不相通的!

1、StringRedisTemplate 往 redis 中存入一個 String 類型的值,分別嘗試獲取值:

  • RedisTemplate 無法獲取到;
  • StringRedisTemplate 可以獲取到;
stringRedisTemplate.opsForValue().set("name", "zhenyu");

Object name1 = redisTemplate.opsForValue().get("name");
System.out.println(name1); // null

String name2 = stringRedisTemplate.opsForValue().get("name");
System.out.println(name2); // zhenyu

注:如果是在客戶端中操作,視爲使用 StringRedisTemplate

2、RedisBuilder 往 redis 中存入一個 User 對象,分別嘗試獲取值:

  • RedisTemplate 可以獲取到;
  • StringRedisTemplate 無法獲取到;
redisTemplate.opsForValue().set("user", new User("21", "zhenyu", 23, new Date()));

User user1 = (User) redisTemplate.opsForValue().get("user");
System.out.println(user1); // User(id=21, name=zhenyu, age=23, bir=Sat Jul 04 10:17:12 CST 2020)

String user2 = stringRedisTemplate.opsForValue().get("user");
System.out.println(user2); // null

3、RedisTemplate 往 redis 中存入一個 String 類型的值,分別嘗試獲取值:

  • RedisTemplate 可以獲取到;
  • StringRedisTemplate 無法獲取到;
redisTemplate.opsForValue().set("name", "hello");

Object name1 = redisTemplate.opsForValue().get("name");
System.out.println(name1); // hello

String name2 = stringRedisTemplate.opsForValue().get("name");
System.out.println(name2); // null

Redis 應用場景

上面我們學習的只是 StringRedisTemplateRedisTemplate 的基礎操作,Redis 真正實現的功能都是建立在這些基礎上的,企業中 Redis 的應用場景主要有:

  1. 利用 Redis 中字符串類型完成 手機驗證碼存儲 的實現;
  2. 利用 Redis 中字符串類型完成 具有失效性業務功能,例如淘寶的訂單失效時間…
  3. 利用 Redis 實現分佈式集羣系統中 Session共享
  4. 利用 Redis 中 ZSet 類型(可排序的 Set 類型)實現 排行榜功能sales(zset) [商品id,商品銷量]
  5. 利用 Redis 實現 分佈式緩存
  6. 利用 Redis 存儲認證之後 token 信息,例如微信小程序開發中獲取的令牌可能會超時…
  7. 利用 Redis 解決分佈式集羣系統中分佈式鎖問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章