SpringBoot整合Redis使用RedisTemplate和StringRedisTemplate
Spring Boot Data(數(shù)據(jù)) Redis 中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是RedisTemplate的子類,兩個(gè)方法基本一致,不同之處主要體現(xiàn)在操作的數(shù)據(jù)類型不同,RedisTemplate中的兩個(gè)泛型都是Object,意味著存儲的key和value都可以是一個(gè)對象,而StringRedisTemplate的兩個(gè)泛型都是String,意味著StringRedisTemplate的key和value都只能是字符串。
注意:
使用RedisTemplate默認(rèn)是將對象序列化到Redis中,所以放入的對象必須實(shí)現(xiàn)對象序列化接口
springboot 2.x后 ,原來使用的 Jedis 被 lettuce 替換。
jedis:采用的直連,多個(gè)線程操作的話,是不安全的。如果要避免不安全,使用jedis pool連接池!更像BIO模式
lettuce:采用netty,實(shí)例可以在多個(gè)線程中共享,不存在線程不安全的情況!可以減少線程數(shù)據(jù)了,更像NIO模式
1.環(huán)境準(zhǔn)備
1.1.引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
1.2.配置application.propertie
# springboot所有的配置類都有一個(gè)自動配置類, xxxAutoConfiguration # 自動配置類都會綁定一個(gè)properties 的配置文件,xxxProperties ??????? spring.redis.host=127.0.0.1 #localhost spring.redis.port=6379 spring.redis.database=0
源碼分析:
@Bean @ConditionalOnMissingBean(name = "redisTemplate") // 可以自己定義一個(gè)redisTemplate來替換這個(gè)默認(rèn)的! public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { // 默認(rèn)的 RedisTemplate 沒有過多的設(shè)置,redis 對象都是需要序列化! // 兩個(gè)泛型都是 Object, Object 的類型,我們后使用需要強(qiáng)制轉(zhuǎn)換 <String, Object> RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean //由于String是redis中最常使用的類型,所以單獨(dú)提一個(gè)bean! public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }
1.3. 連接測試
可以看一下第二節(jié)
redisTemplate 操作不同的數(shù)據(jù)類型,api和我們的指令是一樣的
opsForValue 操作字符串 類似String
opsForList 操作List 類似List
- opsForSet
- opsForHash
- opsForZSet
- opsForGeo
- opsForHyperLogLog
除了進(jìn)本的操作,我們常用的方法都可以直接通過redisTemplate操作,比如事務(wù),和基本的CRUD
獲取redis的連接對象
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection(); connection.flushDb(); connection.flushAll();
2.使用StringRedisTemplate和RedisTemplate
@Autowired private StringRedisTemplate stringRedisTemplate; //對字符串支持比較友好,不能存儲對象 @Autowired private RedisTemplate redisTemplate; //存儲對象 @Test public void testRedisTemplate(){ System.out.println(redisTemplate); //設(shè)置redistemplate值使用對象序列化策略 redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());//指定值使用對象序列化 //redisTemplate.opsForValue().set("user",new User("1","qinyu",99,new Date())); User user = (User) redisTemplate.opsForValue().get("user"); System.out.println(user); //Set keys = redisTemplate.keys("*"); //keys.forEach(key -> System.out.println(key)); /*Object name = redisTemplate.opsForValue().get("name"); System.out.println(name);*/ //Object qinyu= redisTemplate.opsForValue().get("qinyu"); //System.out.println(qinyu); /*redisTemplate.opsForValue().set("name","xxxx"); Object name = redisTemplate.opsForValue().get("name"); System.out.println(name);*/ /*redisTemplate.opsForList().leftPushAll("lists","xxxx","1111"); List lists = redisTemplate.opsForList().range("lists", 0, -1); lists.forEach(list-> System.out.println(list));*/ } /*key的綁定操作 如果日后對某一個(gè)key的操作及其頻繁,可以將這個(gè)key綁定到對應(yīng)redistemplate中,日后基于綁定操作都是操作這個(gè)key boundValueOps 用來對String值綁定key boundListOps 用來對List值綁定key boundSetOps 用來對Set值綁定key boundZsetOps 用來對Zset值綁定key boundHashOps 用來對Hash值綁定key */ @Test public void testBoundKey(){ BoundValueOperations<String, String> nameValueOperations = stringRedisTemplate.boundValueOps("name"); nameValueOperations.set("1"); //yuew nameValueOperations.set("2"); String s = nameValueOperations.get(); System.out.println(s); } //hash相關(guān)操作 opsForHash @Test public void testHash(){ stringRedisTemplate.opsForHash().put("maps","name","qinyu"); Object o = stringRedisTemplate.opsForHash().get("maps", "name"); System.out.println(o); } //zset相關(guān)操作 opsForZSet @Test public void testZSet(){ stringRedisTemplate.opsForZSet().add("zsets","qinyu",10); Set<String> zsets = stringRedisTemplate.opsForZSet().range("zsets", 0, -1); zsets.forEach(value-> System.out.println(value)); } //set相關(guān)操作 opsForSet @Test public void testSet(){ stringRedisTemplate.opsForSet().add("sets","xiaosan","xiaosi","xiaowu"); Set<String> sets = stringRedisTemplate.opsForSet().members("sets"); sets.forEach(value-> System.out.println(value)); } //list相關(guān)的操作opsForList @Test public void testList(){ // stringRedisTemplate.opsForList().leftPushAll("lists","張三","李四","王五"); List<String> lists = stringRedisTemplate.opsForList().range("lists", 0, -1); lists.forEach(key -> System.out.println(key)); } //String相關(guān)的操作 opsForValue @Test public void testString(){ //stringRedisTemplate.opsForValue().set("166","好同學(xué)"); String s = stringRedisTemplate.opsForValue().get("166"); System.out.println(s); Long size = stringRedisTemplate.opsForValue().size("166"); System.out.println(size); } //key相關(guān)的操作 @Test public void test(){ Set<String> keys = stringRedisTemplate.keys("*");//查看所有key Boolean name = stringRedisTemplate.hasKey("name");//判斷某個(gè)key是否存在 stringRedisTemplate.delete("age");//根據(jù)指定key刪除 stringRedisTemplate.rename("","");//修改key的名稱 stringRedisTemplate.expire("key",10, TimeUnit.HOURS); //設(shè)置key超時(shí)時(shí)間 參數(shù)1:設(shè)置key名 參數(shù)2:時(shí)間 參數(shù)3:時(shí)間的單位 stringRedisTemplate.move("",1);//移動key }
3.自定義RedisTemplate
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration public class RedisConfig { // 自己定義一個(gè) RedisTemplate @Bean @SuppressWarnings("all") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { // 我們?yōu)榱俗约洪_發(fā)方便,一般直接使用 <String, Object> RedisTemplate<String, Object> template = new RedisTemplate<String,Object>(); template.setConnectionFactory(factory); // Json序列化配置 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // String 的序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); // key采用String的序列化方式 template.setKeySerializer(stringRedisSerializer); // hash的key也采用String的序列化方式 template.setHashKeySerializer(stringRedisSerializer); // value序列化方式采用jackson template.setValueSerializer(jackson2JsonRedisSerializer); // hash的value序列化方式采用jackson template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } }
4.配置文件
啟動的時(shí)候,就通過配置文件來啟動!
單位 容量單位不區(qū)分大小寫,G和GB有區(qū)別
1.配置文件 unit單位 對大小寫不敏感!
2.包含 可以使用 include 組合多個(gè)配置問題
例如:include /path/to/local.conf
3.網(wǎng)絡(luò)
bind 127.0.0.1 # 綁定的ip protected-mode yes # 保護(hù)模式 port 6379 # 端口設(shè)置
4.通用 GENERAL
daemonize yes # 以守護(hù)進(jìn)程的方式運(yùn)行(就是后臺運(yùn)行),默認(rèn)是 no,我們需要自己開啟為yes! pidfile /var/run/redis_6379.pid # 如果以后臺的方式運(yùn)行,我們就需要指定一個(gè) pid 文件! # 日志 # Specify the server verbosity level. # This can be one of: redis 是內(nèi)存數(shù)據(jù)庫,如果沒有持久化,那么數(shù)據(jù)斷電及失! REPLICATION 復(fù)制,我們后面講解主從復(fù)制的,時(shí)候再進(jìn)行講解 SECURITY 安全 可以在這里設(shè)置redis的密碼,默認(rèn)是沒有密碼! # debug (a lot of information, useful for development/testing) # verbose (many rarely useful info, but not a mess like the debug level) # notice (moderately verbose, what you want in production probably) 生產(chǎn)環(huán)境 # warning (only very important / critical messages are logged) loglevel notice logfile "" # 日志的文件位置名 databases 16 # 數(shù)據(jù)庫的數(shù)量,默認(rèn)是 16 個(gè)數(shù)據(jù)庫 always-show-logo yes # 是否總是顯示LOGO
5.快照
持久化, 在規(guī)定的時(shí)間內(nèi),執(zhí)行了多少次操作,則會持久化到文件 .rdb. aof
redis 是內(nèi)存數(shù)據(jù)庫,如果沒有持久化,那么數(shù)據(jù)斷電及失!
# 如果900s內(nèi),如果至少有一個(gè)1 key進(jìn)行了修改,我們及進(jìn)行持久化操作 save 900 1 # 如果300s內(nèi),如果至少10 key進(jìn)行了修改,我們及進(jìn)行持久化操作 save 300 10 # 如果60s內(nèi),如果至少10000 key進(jìn)行了修改,我們及進(jìn)行持久化操作 save 60 10000 # 之后學(xué)習(xí)持久化,會自己定義這個(gè)測試! stop-writes-on-bgsave-error yes # 持久化如果出錯,是否還需要繼續(xù)工作! 默認(rèn)保存出錯的話停止操作 rdbcompression yes # 是否壓縮 rdb 文件,需要消耗一些cpu資源! rdbchecksum yes # 保存rdb文件的時(shí)候,進(jìn)行錯誤的檢查校驗(yàn)! dir ./ # rdb 文件保存的目錄!
6.SECURITY 安全
可以在這里設(shè)置redis的密碼,默認(rèn)是沒有密碼!
127.0.0.1:6379> ping PONG 127.0.0.1:6379> config get requirepass # 獲取redis的密碼 1) "requirepass" 2) "" 127.0.0.1:6379> config set requirepass "123456" # 設(shè)置redis的密碼 OK 127.0.0.1:6379> config get requirepass # 發(fā)現(xiàn)所有的命令都沒有權(quán)限了 (error) NOAUTH Authentication required. 127.0.0.1:6379> ping (error) NOAUTH Authentication required. 127.0.0.1:6379> auth 123456 # 使用密碼進(jìn)行登錄! OK 127.0.0.1:6379> config get requirepass 1) "requirepass" 2) "123456"
7.限制 CLIENTS
maxclients 10000 # 設(shè)置能連接上redis的最大客戶端的數(shù)量 maxmemory <bytes> # redis 配置最大的內(nèi)存容量 maxmemory-policy noeviction # 內(nèi)存到達(dá)上限之后的處理策略 # redis 中的默認(rèn)的過期策略是 volatile-lru 。 1、volatile-lru:只對設(shè)置了過期時(shí)間的key進(jìn)行LRU(默認(rèn)值) 2、allkeys-lru : 刪除lru算法的key 3、volatile-random:隨機(jī)刪除即將過期key 4、allkeys-random:隨機(jī)刪除 5、volatile-ttl : 刪除即將過期的 6、noeviction : 永不過期,返回錯誤 ------------------------------------------------ # 設(shè)置方式 config set maxmemory-policy volatile-lru
8.APPEND ONLY 模式 aof配置
appendonly no # 默認(rèn)是不開啟aof模式的,默認(rèn)是使用rdb方式持久化的,在大部分所有的情況下, rdb完全夠用! appendfilename "appendonly.aof" # 持久化的文件的名字 # appendfsync always # 每次修改都會 sync。消耗性能 appendfsync everysec # 每秒執(zhí)行一次 sync,可能會丟失這1s的數(shù)據(jù)! # appendfsync no # 不執(zhí)行 sync,這個(gè)時(shí)候操作系統(tǒng)自己同步數(shù)據(jù),速度最快!
9.bgsave
bgsave 是異步進(jìn)行,進(jìn)行持久化的時(shí)候,redis 還可以將繼續(xù)響應(yīng)客戶端請求 ;
bgsave和save對比
命令 | save | bgsave |
---|---|---|
IO類型 | 同步 | 異步 |
阻塞? | 是 | 是(阻塞發(fā)生在fock(),通常非??欤?/td> |
復(fù)雜度 | O(n) | O(n) |
優(yōu)點(diǎn) | 不會消耗額外的內(nèi)存 | 不阻塞客戶端命令 |
缺點(diǎn) | 阻塞客戶端命令 | 需要fock子進(jìn)程,消耗內(nèi)存 |
5.自定義工具類
可以參考下面的鏈接
SpringBoot整合Redis及Redis工具類撰寫實(shí)例
到此這篇關(guān)于SpringBoot整合Redis使用RedisTemplate和StringRedisTemplate的文章就介紹到這了,更多相關(guān)SpringBoot整合Redis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java微信公眾平臺開發(fā)(11) 微信三大平臺的關(guān)聯(lián)
這篇文章主要介紹了Java微信公眾平臺開發(fā)第十一步,微信開發(fā)中微信公眾平臺、開放平臺和商戶平臺的關(guān)聯(lián),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04SpringCloud微服務(wù)的調(diào)用與遠(yuǎn)程調(diào)用測試示例
這篇文章主要介紹了SpringCloud微服務(wù)的調(diào)用與遠(yuǎn)程調(diào)用測試示例,服務(wù)調(diào)用者-可以暫時(shí)認(rèn)為是與用戶交互的角色(因?yàn)榇嬖谖⒎?wù)之間的調(diào)用),可以根據(jù)該用戶的類型將其賦予不同的服務(wù)調(diào)用權(quán)限,通過一次http請求訪問調(diào)用對應(yīng)的微服務(wù)獲取想要的數(shù)據(jù)2023-04-04MyBatis中如何查詢某個(gè)時(shí)間段內(nèi)的數(shù)據(jù)
這篇文章主要介紹了MyBatis中如何查詢某個(gè)時(shí)間段內(nèi)的數(shù)據(jù),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08Java實(shí)現(xiàn)mysql數(shù)據(jù)庫的自動備份和自動還原
這篇文章主要為大家詳細(xì)介紹了如何通過Java實(shí)現(xiàn)mysql數(shù)據(jù)庫的自動備份和自動還原,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2024-11-11深入理解Java中的final關(guān)鍵字_動力節(jié)點(diǎn)Java學(xué)院整理
Java中的final關(guān)鍵字非常重要,它可以應(yīng)用于類、方法以及變量。這篇文章中我將帶你看看什么是final關(guān)鍵字以及使用final的好處,具體內(nèi)容詳情通過本文學(xué)習(xí)吧2017-04-04使用hutool工具進(jìn)行導(dǎo)入導(dǎo)出excel表格
如何在后臺添加導(dǎo)入導(dǎo)出表格的功能呢,本期的文章將會帶領(lǐng)小伙伴們一起實(shí)現(xiàn)此功能,文中有詳細(xì)的代碼示例和圖文介紹,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-10-10多線程-lock與lockInterruptibly的區(qū)別及說明
文章主要討論了Java中ReentrantLock的lock和lockInterruptibly方法的區(qū)別,以及AQS中的雙向鏈表設(shè)計(jì),lock方法不響應(yīng)中斷,而lockInterruptibly方法會響應(yīng)中斷,AQS的雙向鏈表設(shè)計(jì)使得線程管理更加高效和靈活,適用于高并發(fā)場景2025-02-02