淺析SpringDataRedis、RedisTemplate Api的使用及如何使用RedisTemplate操作Redis的5種數據類型、StringRedisTemplate和RedisTemplate的區別


一、SpringDataRedis簡介

1、Redis:redis是一款開源的Key-Value數據庫,運行在內存中,由C語言編寫。企業開發通常采用Redis來實現緩存。同類的產品還有memcache 、memcached 等。

2、Jedis:Jedis是Redis官方推出的一款面向Java的客戶端,提供了很多接口供Java語言調用。可以在Redis官網下載,當然還有一些開源愛好者提供的客戶端,如Jredis、SRP等等,推薦使用Jedis。

3、Spring Data Redis

  Spring-data-redis是spring大家族的一部分,提供了在srping應用中通過簡單的配置訪問redis服務,對reids底層開發包(Jedis, JRedis, and RJC)進行了高度封裝,RedisTemplate提供了redis各種操作、異常處理及序列化,支持發布訂閱,並對spring 3.1 cache進行了實現。

  spring-data-redis針對jedis提供了如下功能:

(1)連接池自動管理,提供了一個高度封裝的“RedisTemplate”類

(2)針對jedis客戶端中大量api進行了歸類封裝,將同一類型操作封裝為operation接口。

  ValueOperations:簡單K-V操作

  SetOperations:set類型數據操作

  ZSetOperations:zset類型數據操作

  HashOperations:針對map類型的數據操作

  ListOperations:針對list類型的數據操作

(3)提供了對key的“bound”(綁定)便捷化操作API,可以通過bound封裝指定的key,然后進行一系列的操作而無須“顯式”的再次指定Key,即BoundKeyOperations:

  BoundValueOperations、BoundSetOperations、BoundListOperations、BoundSetOperations、BoundHashOperations

(4)將事務操作封裝,有容器控制。

(5)針對數據的“序列化/反序列化”,提供了多種可選擇策略(RedisSerializer)

  JdkSerializationRedisSerializer:POJO對象的存取場景,使用JDK本身序列化機制,將pojo類通過ObjectInputStream/ObjectOutputStream進行序列化操作,最終redis-server中將存儲字節序列。是目前最常用的序列化策略。

  StringRedisSerializer:Key或者value為字符串的場景,根據指定的charset對數據的字節序列編碼成string,是“new String(bytes, charset)”和“string.getBytes(charset)”的直接封裝。是最輕量級和高效的策略。

  JacksonJsonRedisSerializer:jackson-json工具提供了javabean與json之間的轉換能力,可以將pojo實例序列化成json格式存儲在redis中,也可以將json格式的數據轉換成pojo實例。因為jackson工具在序列化和反序列化時,需要明確指定Class類型,因此此策略封裝起來稍微復雜。【需要jackson-mapper-asl工具支持】

二、RedisTemplate中API使用

1、pom.xml導入依賴

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

2、配置文件

spring: redis: host: ***   // ip
    port: 6379  // 端口
    password: *** // 密碼
# Redis服務器連接端口 spring.redis.port=6379 # Redis服務器地址 spring.redis.host=127.0.0.1 # Redis數據庫索引(默認為0) spring.redis.database=0 # Redis服務器連接密碼(默認為空) spring.redis.password= # 連接池最大連接數(使用負值表示沒有限制) spring.redis.jedis.pool.max-active=8 # 連接池最大阻塞等待時間(使用負值表示沒有限制) spring.redis.jedis.pool.max-wait=-1ms # 連接池中的最大空閑連接 spring.redis.jedis.pool.max-idle=8 # 連接池中的最小空閑連接 spring.redis.jedis.pool.min-idle=0 # 連接超時時間(毫秒) spring.redis.timeout=5000ms

3、RedisTemplate的直接方法

  首先使用@Autowired注入RedisTemplate

@Autowired private RedisTemplate redisTemplate; // 1、刪除單個key
public void delete(String key){ redisTemplate.delete(key); } // 2、刪除多個key
public void deleteKey (String ...keys){ redisTemplate.delete(keys); } // 3、指定key的失效時間
public void expire(String key,long time){ redisTemplate.expire(key,time,TimeUnit.MINUTES); } // 4、根據key獲取過期時間
public long getExpire(String key){ Long expire = redisTemplate.getExpire(key); return expire; } // 5、判斷key是否存在
public boolean hasKey(String key){ return redisTemplate.hasKey(key); }

三、Redis的各種不同類型的操作

1、String類型相關操作

// 1)、添加緩存(2/3是1的遞進值) //1、通過redisTemplate設置值
redisTemplate.boundValueOps("StringKey").set("StringValue"); redisTemplate.boundValueOps("StringKey").set("StringValue",1, TimeUnit.MINUTES); //2、通過BoundValueOperations設置值
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey"); stringKey.set("StringVaule"); stringKey.set("StringValue",1, TimeUnit.MINUTES); //3、通過ValueOperations設置值
ValueOperations ops = redisTemplate.opsForValue(); ops.set("StringKey", "StringVaule"); ops.set("StringValue","StringVaule",1, TimeUnit.MINUTES); // 2)、設置過期時間(單獨設置)
redisTemplate.boundValueOps("StringKey").expire(1,TimeUnit.MINUTES); redisTemplate.expire("StringKey",1,TimeUnit.MINUTES); // 3)、獲取緩存值(2/3是1的遞進值) //1、通過redisTemplate設置值
String str1 = (String) redisTemplate.boundValueOps("StringKey").get(); //2、通過BoundValueOperations獲取值
BoundValueOperations stringKey = redisTemplate.boundValueOps("StringKey"); String str2 = (String) stringKey.get(); //3、通過ValueOperations獲取值
ValueOperations ops = redisTemplate.opsForValue(); String str3 = (String) ops.get("StringKey"); // 4)、刪除key
Boolean result = redisTemplate.delete("StringKey"); // 5)、順序遞增
redisTemplate.boundValueOps("StringKey").increment(3L); // 6)、順序遞減
redisTemplate.boundValueOps("StringKey").increment(-3L);

2、Hash類型相關操作

// 1)、添加緩存(2/3是1的遞進值) //1、通過redisTemplate設置值
redisTemplate.boundHashOps("HashKey").put("SmallKey", "HashVaue"); //2、通過BoundValueOperations設置值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey"); hashKey.put("SmallKey", "HashVaue"); //3、通過ValueOperations設置值
HashOperations hashOps = redisTemplate.opsForHash(); hashOps.put("HashKey", "SmallKey", "HashVaue"); // 2)、設置過期時間(單獨設置)
redisTemplate.boundValueOps("HashKey").expire(1,TimeUnit.MINUTES); redisTemplate.expire("HashKey",1,TimeUnit.MINUTES); // 3)、添加一個Map集合
HashMap<String, String> hashMap = new HashMap<>(); redisTemplate.boundHashOps("HashKey").putAll(hashMap ); // 4)、設置過期時間(單獨設置)
redisTemplate.boundValueOps("HashKey").expire(1,TimeUnit.MINUTES); redisTemplate.expire("HashKey",1,TimeUnit.MINUTES); // 5)、提取所有的小key //1、通過redisTemplate獲取值
Set keys1 = redisTemplate.boundHashOps("HashKey").keys(); //2、通過BoundValueOperations獲取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey"); Set keys2 = hashKey.keys(); //3、通過ValueOperations獲取值
HashOperations hashOps = redisTemplate.opsForHash(); Set keys3 = hashOps.keys("HashKey"); // 6)、提取所有的value值 //1、通過redisTemplate獲取值
List values1 = redisTemplate.boundHashOps("HashKey").values(); //2、通過BoundValueOperations獲取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey"); List values2 = hashKey.values(); //3、通過ValueOperations獲取值
HashOperations hashOps = redisTemplate.opsForHash(); List values3 = hashOps.values("HashKey"); // 7)、根據key提取value值 //1、通過redisTemplate獲取
String value1 = (String) redisTemplate.boundHashOps("HashKey").get("SmallKey"); //2、通過BoundValueOperations獲取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey"); String value2 = (String) hashKey.get("SmallKey"); //3、通過ValueOperations獲取值
HashOperations hashOps = redisTemplate.opsForHash(); String value3 = (String) hashOps.get("HashKey", "SmallKey"); // 8)、獲取所有的鍵值對集合 //1、通過redisTemplate獲取
Map entries = redisTemplate.boundHashOps("HashKey").entries(); //2、通過BoundValueOperations獲取值
BoundHashOperations hashKey = redisTemplate.boundHashOps("HashKey"); Map entries1 = hashKey.entries(); //3、通過ValueOperations獲取值
HashOperations hashOps = redisTemplate.opsForHash(); Map entries2 = hashOps.entries("HashKey"); // 9)、刪除 //刪除小key
redisTemplate.boundHashOps("HashKey").delete("SmallKey"); //刪除大key
redisTemplate.delete("HashKey"); // 10)、判斷Hash中是否含有該值
Boolean isEmpty = redisTemplate.boundHashOps("HashKey").hasKey("SmallKey");

3、Set類型相關操作

// 1)、添加Set緩存(值可以是一個,也可是多個)(2/3是1的遞進值) //1、通過redisTemplate設置值
redisTemplate.boundSetOps("setKey").add("setValue1", "setValue2", "setValue3"); //2、通過BoundValueOperations設置值
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey"); setKey.add("setValue1", "setValue2", "setValue3"); //3、通過ValueOperations設置值
SetOperations setOps = redisTemplate.opsForSet(); setOps.add("setKey", "SetValue1", "setValue2", "setValue3"); // 2)、設置過期時間(單獨設置)
redisTemplate.boundValueOps("setKey").expire(1,TimeUnit.MINUTES); redisTemplate.expire("setKey",1,TimeUnit.MINUTES); // 3)、根據key獲取Set中的所有值 //1、通過redisTemplate獲取值
Set set1 = redisTemplate.boundSetOps("setKey").members(); //2、通過BoundValueOperations獲取值
BoundSetOperations setKey = redisTemplate.boundSetOps("setKey"); Set set2 = setKey.members(); //3、通過ValueOperations獲取值
SetOperations setOps = redisTemplate.opsForSet(); Set set3 = setOps.members("setKey"); // 4)、根據value從一個set中查詢,是否存在
Boolean isEmpty = redisTemplate.boundSetOps("setKey").isMember("setValue2"); // 5)、獲取Set緩存的長度
Long size = redisTemplate.boundSetOps("setKey").size(); // 6)、移除指定的元素
 Long result1 = redisTemplate.boundSetOps("setKey").remove("setValue1"); // 7)、移除指定的key
Boolean result2 = redisTemplate.delete("setKey");

4、LIST類型相關操作

// 1)、添加緩存(2/3是1的遞進值) //1、通過redisTemplate設置值
redisTemplate.boundListOps("listKey").leftPush("listLeftValue1"); redisTemplate.boundListOps("listKey").rightPush("listRightValue2"); //2、通過BoundValueOperations設置值
BoundListOperations listKey = redisTemplate.boundListOps("listKey"); listKey.leftPush("listLeftValue3"); listKey.rightPush("listRightValue4"); //3、通過ValueOperations設置值
ListOperations opsList = redisTemplate.opsForList(); opsList.leftPush("listKey", "listLeftValue5"); opsList.rightPush("listKey", "listRightValue6"); // 2)、將List放入緩存
ArrayList<String> list = new ArrayList<>(); redisTemplate.boundListOps("listKey").rightPushAll(list); redisTemplate.boundListOps("listKey").leftPushAll(list); // 3)、設置過期時間(單獨設置)
redisTemplate.boundValueOps("listKey").expire(1,TimeUnit.MINUTES); redisTemplate.expire("listKey",1,TimeUnit.MINUTES); // 4)、獲取List緩存全部內容(起始索引,結束索引)
List listKey1 = redisTemplate.boundListOps("listKey").range(0, 10); // 5)、從左或從右彈出一個元素
String listKey2 = (String) redisTemplate.boundListOps("listKey").leftPop();  //從左側彈出一個元素
String listKey3 = (String) redisTemplate.boundListOps("listKey").rightPop(); //從右側彈出一個元素 // 6)、根據索引查詢元素
String listKey4 = (String) redisTemplate.boundListOps("listKey").index(1); // 7)、獲取List緩存的長度
Long size = redisTemplate.boundListOps("listKey").size(); // 8)、根據索引修改List中的某條數據(key,索引,值)
redisTemplate.boundListOps("listKey").set(3L,"listLeftValue3"); // 9)、移除N個值為value(key,移除個數,值)
redisTemplate.boundListOps("listKey").remove(3L,"value");

5、Zset類型的相關操作

// 1)、向集合中插入元素,並設置分數 //1、通過redisTemplate設置值
redisTemplate.boundZSetOps("zSetKey").add("zSetVaule", 100D); //2、通過BoundValueOperations設置值
BoundZSetOperations zSetKey = redisTemplate.boundZSetOps("zSetKey"); zSetKey.add("zSetVaule", 100D); //3、通過ValueOperations設置值
ZSetOperations zSetOps = redisTemplate.opsForZSet(); zSetOps.add("zSetKey", "zSetVaule", 100D); // 2)、向集合中插入多個元素,並設置分數
DefaultTypedTuple<String> p1 = new DefaultTypedTuple<>("zSetVaule1", 2.1D); DefaultTypedTuple<String> p2 = new DefaultTypedTuple<>("zSetVaule2", 3.3D); redisTemplate.boundZSetOps("zSetKey").add(new HashSet<>(Arrays.asList(p1,p2))); // 3)、按照排名先后(從小到大)打印指定區間內的元素, -1為打印全部
Set<String> range = redisTemplate.boundZSetOps("zSetKey").range(0, -1); // 4)、獲得指定元素的分數
Double score = redisTemplate.boundZSetOps("zSetKey").score("zSetVaule"); // 5)、返回集合內的成員個數
Long size = redisTemplate.boundZSetOps("zSetKey").size(); // 6)、返回集合內指定分數范圍的成員個數(Double類型)
Long COUNT = redisTemplate.boundZSetOps("zSetKey").count(0D, 2.2D); // 7)、返回集合內元素在指定分數范圍內的排名(從小到大)
Set byScore = redisTemplate.boundZSetOps("zSetKey").rangeByScore(0D, 2.2D); // 8)、帶偏移量和個數,(key,起始分數,最大分數,偏移量,個數)
Set<String> ranking2 = redisTemplate.opsForZSet().rangeByScore("zSetKey", 0D, 2.2D 1, 3); // 9)、返回集合內元素的排名,以及分數(從小到大)
Set<TypedTuple<String>> tuples = redisTemplate.boundZSetOps("zSetKey").rangeWithScores(0L, 3L); for (TypedTuple<String> tuple : tuples) {   System.out.println(tuple.getValue() + " : " + tuple.getScore()); } // 10)、返回指定成員的排名 //從小到大
Long startRank = redisTemplate.boundZSetOps("zSetKey").rank("zSetVaule"); //從大到小
Long endRank = redisTemplate.boundZSetOps("zSetKey").reverseRank("zSetVaule"); // 11)、從集合中刪除指定元素
redisTemplate.boundZSetOps("zSetKey").remove("zSetVaule"); // 12)、刪除指定索引范圍的元素(Long類型)
redisTemplate.boundZSetOps("zSetKey").removeRange(0L,3L); // 13)、刪除指定分數范圍內的元素(Double類型)
redisTemplate.boundZSetOps("zSetKey").removeRangeByScorssse(0D,2.2D); // 14)、為指定元素加分(Double類型)
Double score = redisTemplate.boundZSetOps("zSetKey").incrementScore("zSetVaule",1.1D);

  一般都會有RedisTemplate操作的工具類,比如RedisUtil,有封裝很多常用的方法,可以在網上搜一下,然后直接使用。

四、StringRedisTemplate和RedisTemplate

1、RedisTemplate和StringRedisTemplate的區別:

  兩者的關系是StringRedisTemplate繼承RedisTemplate。

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

  SDR默認采用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。

  StringRedisTemplate默認采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。(StringRedisSerializer

  RedisTemplate默認采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。(JdkSerializationRedisSerializer)

2、StringRedistemplate的源碼

package org.springframework.data.redis.core; import org.springframework.data.redis.connection.DefaultStringRedisConnection; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.RedisSerializer; public class StringRedisTemplate extends RedisTemplate<String, String> { public StringRedisTemplate() { this.setKeySerializer(RedisSerializer.string()); this.setValueSerializer(RedisSerializer.string()); this.setHashKeySerializer(RedisSerializer.string()); this.setHashValueSerializer(RedisSerializer.string()); } public StringRedisTemplate(RedisConnectionFactory connectionFactory) { this(); this.setConnectionFactory(connectionFactory); this.afterPropertiesSet(); } protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) { return new DefaultStringRedisConnection(connection); } }

  從上面創建StringRedisTemplate的無參構造方法可以看出,此時將keySerializer、valueSerializer、hashKeySerializer、hashValueSerializer的序列化方式為stringSerializer,也就是StringRedisSerializer序列化方式;此時執行完整個方法后,還需要接着執行setConnectionFactory()方法,然后轉向他的父類RedisTemplate中的afterPropertiesSet方法,此時上述四個序列化方式已經設置;

3、Redis使用的區別

  RedisTemplate使用的序列類在在操作數據的時候,比如說存入數據會將數據先序列化成字節數組然后在存入Redis數據庫,這個時候打開Redis查看的時候,你會看到你的數據不是以可讀的形式展現的,而是以字節數組顯示,類似下面(RedisTemplate)

  當然從Redis獲取數據的時候也會默認將數據當做字節數組轉化,這樣就會導致一個問題,當需要獲取的數據不是以字節數組存在redis當中而是正常的可讀的字符串的時候,比如說下面這種形式的數據(StringRedisTemplate)

  當Redis當中的數據值是以數組形式顯示出來的時候,只能使用RedisTemplate才能獲取到里面的數據。

  當Redis當中的數據值是以可讀的形式顯示出來的時候,只能使用StringRedisTemplate才能獲取到里面的數據。

  所以當你使用RedisTemplate獲取不到數據為NULL時,一般是獲取的方式錯誤。檢查一下數據是否可讀即可。

4、使用總結:

  StringRedisTemplate:當你的redis數據庫里面本來存的是字符串數據或者你要存取的數據就是字符串類型數據的時候。

  RedisTemplate:但是如果你的數據是復雜的對象類型,而取出的時候又不想做任何的數據轉換,直接從Redis里面取出一個對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM